diff -u --recursive --new-file pre1/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- pre1/linux/Documentation/DocBook/kernel-hacking.tmpl Thu Dec 20 08:54:23 2001
+++ linux/Documentation/DocBook/kernel-hacking.tmpl Tue Jan 15 13:53:50 2002
@@ -371,8 +371,7 @@
-if (current->need_resched)
- schedule(); /* Will sleep */
+cond_resched(); /* Will sleep */
diff -u --recursive --new-file pre1/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- pre1/linux/Documentation/ioctl-number.txt Wed Jul 11 16:35:37 2001
+++ linux/Documentation/ioctl-number.txt Thu Jan 17 14:06:53 2002
@@ -101,7 +101,8 @@
'S' 82-FF scsi/scsi.h conflict!
'T' all linux/soundcard.h conflict!
'T' all asm-i386/ioctls.h conflict!
-'U' all linux/drivers/usb/usb.h
+'U' 00-EF linux/drivers/usb/usb.h
+'U' F0-FF drivers/usb/auerswald.c
'V' all linux/vt.h
'W' 00-1F linux/watchdog.h conflict!
'W' 00-1F linux/wanrouter.h conflict!
diff -u --recursive --new-file pre1/linux/Makefile linux/Makefile
--- pre1/linux/Makefile Wed Jan 16 11:16:28 2002
+++ linux/Makefile Wed Jan 16 11:14:10 2002
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 3
-EXTRAVERSION =-pre1
+EXTRAVERSION =-pre2
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -u --recursive --new-file pre1/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- pre1/linux/arch/arm/kernel/ecard.c Wed Jan 16 11:16:28 2002
+++ linux/arch/arm/kernel/ecard.c Thu Jan 17 14:21:16 2002
@@ -1097,6 +1097,8 @@
ecard_proc_init();
}
+subsys_initcall(ecard_init);
+
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
EXPORT_SYMBOL(ecard_readchunk);
diff -u --recursive --new-file pre1/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- pre1/linux/arch/arm/kernel/process.c Sat Jan 5 13:04:30 2002
+++ linux/arch/arm/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -91,7 +91,7 @@
if (!idle)
idle = arch_idle;
leds_event(led_idle_start);
- while (!current->need_resched)
+ while (!need_resched())
idle();
leds_event(led_idle_end);
schedule();
diff -u --recursive --new-file pre1/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- pre1/linux/arch/i386/kernel/apm.c Fri Nov 30 08:38:44 2001
+++ linux/arch/i386/kernel/apm.c Tue Jan 15 13:53:50 2002
@@ -766,14 +766,14 @@
start_idle = jiffies;
while (1) {
- if (!current->need_resched) {
+ if (!need_resched()) {
if (jiffies - start_idle < HARD_IDLE_TIMEOUT) {
if (!current_cpu_data.hlt_works_ok)
continue;
if (hlt_counter)
continue;
__cli();
- if (!current->need_resched)
+ if (!need_resched())
safe_halt();
else
__sti();
diff -u --recursive --new-file pre1/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- pre1/linux/arch/i386/kernel/mca.c Thu Aug 24 12:52:32 2000
+++ linux/arch/i386/kernel/mca.c Thu Jan 17 14:21:16 2002
@@ -311,6 +311,8 @@
#endif
}
+subsys_initcall(mca_init);
+
/*--------------------------------------------------------------------*/
static void mca_handle_nmi_slot(int slot, int check_flag)
diff -u --recursive --new-file pre1/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- pre1/linux/arch/i386/kernel/process.c Mon Jan 7 12:55:17 2002
+++ linux/arch/i386/kernel/process.c Tue Jan 15 14:33:55 2002
@@ -42,7 +42,6 @@
#include
#include
#include
-#include
#ifdef CONFIG_MATH_EMULATION
#include
#endif
@@ -81,7 +80,7 @@
{
if (current_cpu_data.hlt_works_ok && !hlt_counter) {
__cli();
- if (!current->need_resched)
+ if (!need_resched())
safe_halt();
else
__sti();
@@ -127,7 +126,7 @@
void (*idle)(void) = pm_idle;
if (!idle)
idle = default_idle;
- while (!current->need_resched)
+ while (!need_resched())
idle();
schedule();
check_pgt_cache();
diff -u --recursive --new-file pre1/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- pre1/linux/arch/i386/math-emu/fpu_entry.c Fri Apr 6 10:42:47 2001
+++ linux/arch/i386/math-emu/fpu_entry.c Tue Jan 15 13:53:50 2002
@@ -559,7 +559,7 @@
RE_ENTRANT_CHECK_ON;
#endif /* DEBUG */
- if (FPU_lookahead && !current->need_resched)
+ if (FPU_lookahead && !need_resched())
{
FPU_ORIG_EIP = FPU_EIP - code_base;
if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
diff -u --recursive --new-file pre1/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- pre1/linux/arch/i386/vmlinux.lds Mon Jul 2 14:40:14 2001
+++ linux/arch/i386/vmlinux.lds Thu Jan 17 14:21:16 2002
@@ -48,7 +48,15 @@
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff -u --recursive --new-file pre1/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- pre1/linux/arch/ia64/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/ia64/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -117,10 +117,10 @@
while (1) {
#ifdef CONFIG_SMP
- if (!current->need_resched)
+ if (!need_resched())
min_xtp();
#endif
- while (!current->need_resched)
+ while (!need_resched())
continue;
#ifdef CONFIG_SMP
normal_xtp();
diff -u --recursive --new-file pre1/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- pre1/linux/arch/m68k/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/m68k/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -56,7 +56,7 @@
static void default_idle(void)
{
while(1) {
- if (!current->need_resched)
+ if (!need_resched())
#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
/* block out HSYNC on the atari (falcon) */
__asm__("stop #0x2200" : : : "cc");
diff -u --recursive --new-file pre1/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- pre1/linux/arch/mips/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/mips/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -39,7 +39,7 @@
init_idle();
while (1) {
- while (!current->need_resched)
+ while (!need_resched())
if (cpu_wait)
(*cpu_wait)();
schedule();
diff -u --recursive --new-file pre1/linux/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c
--- pre1/linux/arch/mips/math-emu/cp1emu.c Sun Sep 9 10:43:01 2001
+++ linux/arch/mips/math-emu/cp1emu.c Tue Jan 15 13:53:50 2002
@@ -1674,8 +1674,7 @@
oldepc = xcp->cp0_epc;
do {
- if (current->need_resched)
- schedule();
+ cond_resched();
prevepc = xcp->cp0_epc;
insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
diff -u --recursive --new-file pre1/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c
--- pre1/linux/arch/mips64/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/mips64/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -35,7 +35,7 @@
init_idle();
current->nice = 20;
while (1) {
- while (!current->need_resched)
+ while (!need_resched())
if (wait_available)
__asm__("wait");
schedule();
diff -u --recursive --new-file pre1/linux/arch/mips64/math-emu/cp1emu.c linux/arch/mips64/math-emu/cp1emu.c
--- pre1/linux/arch/mips64/math-emu/cp1emu.c Sun Sep 9 10:43:02 2001
+++ linux/arch/mips64/math-emu/cp1emu.c Tue Jan 15 13:53:50 2002
@@ -1707,8 +1707,7 @@
oldepc = xcp->cp0_epc;
do {
- if (current->need_resched)
- schedule();
+ cond_resched();
prevepc = xcp->cp0_epc;
insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
diff -u --recursive --new-file pre1/linux/arch/parisc/kernel/process.c linux/arch/parisc/kernel/process.c
--- pre1/linux/arch/parisc/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/parisc/kernel/process.c Tue Jan 15 13:57:50 2002
@@ -73,8 +73,8 @@
current->nice = 20;
while (1) {
- while (!current->need_resched) {
- }
+ while (!need_resched())
+ barrier();
schedule();
check_pgt_cache();
}
diff -u --recursive --new-file pre1/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- pre1/linux/arch/ppc/kernel/idle.c Thu Dec 27 08:21:28 2001
+++ linux/arch/ppc/kernel/idle.c Tue Jan 15 13:57:16 2002
@@ -66,15 +66,15 @@
int oldval = xchg(¤t->need_resched, -1);
if (!oldval) {
- while(current->need_resched == -1)
- ; /* Do Nothing */
+ while (need_resched())
+ barrier(); /* Do Nothing */
}
}
#endif
- if (do_power_save && !current->need_resched)
+ if (do_power_save && !need_resched())
power_save();
- if (current->need_resched) {
+ if (need_resched()) {
schedule();
check_pgt_cache();
}
@@ -150,7 +150,7 @@
if ( atomic_read(&zero_cache_sz) >= zero_cache_water[0] )
return;
- while ( (atomic_read(&zero_cache_sz) < zero_cache_water[1]) && (!current->need_resched) )
+ while ( (atomic_read(&zero_cache_sz) < zero_cache_water[1]) && !need_resched() )
{
/*
* Mark a page as reserved so we can mess with it
@@ -161,8 +161,7 @@
if ( !pageptr )
return;
- if ( current->need_resched )
- schedule();
+ cond_resched();
/*
* Make the page no cache so we don't blow our cache with 0's
@@ -181,8 +180,7 @@
*/
for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 )
{
- if ( current->need_resched )
- schedule();
+ cond_resched();
*(unsigned long *)(bytecount + pageptr) = 0;
}
@@ -243,7 +241,7 @@
* -- Cort
*/
_nmask_and_or_msr(MSR_EE, 0);
- if (!current->need_resched)
+ if (!need_resched())
{
asm("mfspr %0,1008" : "=r" (hid0) :);
hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
diff -u --recursive --new-file pre1/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- pre1/linux/arch/ppc/kernel/setup.c Wed Jan 16 11:16:28 2002
+++ linux/arch/ppc/kernel/setup.c Thu Jan 17 14:21:16 2002
@@ -535,6 +535,8 @@
}
}
+subsys_initcall(ppc_init);
+
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
{
diff -u --recursive --new-file pre1/linux/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c
--- pre1/linux/arch/s390/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/s390/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -60,7 +60,7 @@
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L;
while(1) {
- if (current->need_resched) {
+ if (need_resched()) {
schedule();
check_pgt_cache();
continue;
diff -u --recursive --new-file pre1/linux/arch/s390x/kernel/process.c linux/arch/s390x/kernel/process.c
--- pre1/linux/arch/s390x/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/s390x/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -60,7 +60,7 @@
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.addr = (unsigned long) &&idle_wakeup;
while(1) {
- if (current->need_resched) {
+ if (need_resched()) {
schedule();
check_pgt_cache();
continue;
diff -u --recursive --new-file pre1/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c
--- pre1/linux/arch/sh/kernel/process.c Thu Dec 27 08:21:28 2001
+++ linux/arch/sh/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -44,11 +44,11 @@
while (1) {
if (hlt_counter) {
- if (current->need_resched)
+ if (need_resched())
break;
} else {
__cli();
- while (!current->need_resched) {
+ while (!need_resched()) {
__sti();
asm volatile("sleep" : : : "memory");
__cli();
diff -u --recursive --new-file pre1/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- pre1/linux/arch/sparc/kernel/process.c Mon Jan 14 10:10:43 2002
+++ linux/arch/sparc/kernel/process.c Tue Jan 15 13:53:50 2002
@@ -106,7 +106,7 @@
{
/* endless idle loop with no priority at all */
while(1) {
- if(current->need_resched) {
+ if(need_resched()) {
schedule();
check_pgt_cache();
}
diff -u --recursive --new-file pre1/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- pre1/linux/arch/sparc64/kernel/process.c Mon Jan 14 10:10:44 2002
+++ linux/arch/sparc64/kernel/process.c Tue Jan 15 13:53:51 2002
@@ -61,7 +61,7 @@
* But this requires writing back the contents of the
* L2 cache etc. so implement this later. -DaveM
*/
- while (!current->need_resched)
+ while (!need_resched())
barrier();
schedule();
@@ -80,7 +80,7 @@
int cpu_idle(void)
{
while(1) {
- if (current->need_resched != 0) {
+ if (need_resched()) {
unidle_me();
schedule();
check_pgt_cache();
diff -u --recursive --new-file pre1/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- pre1/linux/drivers/block/ll_rw_blk.c Thu Jan 10 10:15:38 2002
+++ linux/drivers/block/ll_rw_blk.c Thu Jan 17 13:59:33 2002
@@ -186,7 +186,8 @@
* full 4GB zone, so we have to resort to low memory for any bounces.
* ISA has its own < 16MB zone.
*/
- if (dma_addr == BLK_BOUNCE_ISA) {
+ if (bounce_pfn < blk_max_low_pfn) {
+ BUG_ON(dma_addr < BLK_BOUNCE_ISA);
init_emergency_isa_pool();
q->bounce_gfp = GFP_NOIO | GFP_DMA;
} else
@@ -302,8 +303,8 @@
static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER",
"REQ_CMD", "REQ_NOMERGE", "REQ_STARTED",
"REQ_DONTPREP", "REQ_DRIVE_CMD", "REQ_DRIVE_TASK",
- "REQ_PC", "REQ_BLOCK_PC", "REQ_SENSE",
- "REQ_SPECIAL" };
+ "REQ_DRIVE_ACB", "REQ_PC", "REQ_BLOCK_PC",
+ "REQ_SENSE", "REQ_SPECIAL" };
void blk_dump_rq_flags(struct request *rq, char *msg)
{
@@ -1708,7 +1709,11 @@
printk("block: %d slots per queue, batch=%d\n", queue_nr_requests, batch_requests);
blk_max_low_pfn = max_low_pfn;
+#ifdef CONFIG_HIGHMEM
blk_max_pfn = max_pfn;
+#else
+ blk_max_pfn = max_low_pfn;
+#endif
#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE)
ide_init(); /* this MUST precede hd_init */
diff -u --recursive --new-file pre1/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- pre1/linux/drivers/char/lp.c Fri Jan 4 21:19:50 2002
+++ linux/drivers/char/lp.c Tue Jan 15 13:53:51 2002
@@ -367,7 +367,7 @@
= lp_negotiate (port,
lp_table[minor].best_mode);
- } else if (current->need_resched)
+ } else if (need_resched())
schedule ();
if (count) {
diff -u --recursive --new-file pre1/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- pre1/linux/drivers/char/mem.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/char/mem.c Tue Jan 15 13:53:51 2002
@@ -381,8 +381,7 @@
unsigned long unwritten = clear_user(buf, PAGE_SIZE);
if (unwritten)
return size + unwritten - PAGE_SIZE;
- if (current->need_resched)
- schedule();
+ cond_resched();
buf += PAGE_SIZE;
size -= PAGE_SIZE;
} while (size);
diff -u --recursive --new-file pre1/linux/drivers/char/mwave/3780i.c linux/drivers/char/mwave/3780i.c
--- pre1/linux/drivers/char/mwave/3780i.c Sun Sep 30 12:26:05 2001
+++ linux/drivers/char/mwave/3780i.c Tue Jan 15 13:53:51 2002
@@ -68,11 +68,9 @@
static void PaceMsaAccess(unsigned short usDspBaseIO)
{
- if(current->need_resched)
- schedule();
+ cond_resched();
udelay(100);
- if(current->need_resched)
- schedule();
+ cond_resched();
}
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
diff -u --recursive --new-file pre1/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- pre1/linux/drivers/char/ppdev.c Tue Jan 1 18:55:31 2002
+++ linux/drivers/char/ppdev.c Tue Jan 15 13:53:51 2002
@@ -170,9 +170,7 @@
break;
}
- if (current->need_resched) {
- schedule ();
- }
+ cond_resched();
}
kfree (kbuffer);
@@ -242,9 +240,7 @@
break;
}
- if (current->need_resched) {
- schedule ();
- }
+ cond_resched();
}
kfree (kbuffer);
diff -u --recursive --new-file pre1/linux/drivers/char/random.c linux/drivers/char/random.c
--- pre1/linux/drivers/char/random.c Fri Nov 9 14:01:21 2001
+++ linux/drivers/char/random.c Tue Jan 15 13:53:51 2002
@@ -1313,7 +1313,7 @@
/*
* Check if we need to break out or reschedule....
*/
- if ((flags & EXTRACT_ENTROPY_USER) && current->need_resched) {
+ if ((flags & EXTRACT_ENTROPY_USER) && need_resched()) {
if (signal_pending(current)) {
if (ret == 0)
ret = -ERESTARTSYS;
diff -u --recursive --new-file pre1/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- pre1/linux/drivers/char/tty_io.c Thu Jan 3 13:22:21 2002
+++ linux/drivers/char/tty_io.c Tue Jan 15 13:53:51 2002
@@ -712,8 +712,7 @@
ret = -ERESTARTSYS;
if (signal_pending(current))
break;
- if (current->need_resched)
- schedule();
+ cond_resched();
}
}
if (written) {
diff -u --recursive --new-file pre1/linux/drivers/dio/dio.c linux/drivers/dio/dio.c
--- pre1/linux/drivers/dio/dio.c Fri Feb 9 11:30:23 2001
+++ linux/drivers/dio/dio.c Thu Jan 17 14:21:16 2002
@@ -208,6 +208,8 @@
}
}
+subsys_initcall(dio_init);
+
/* Bear in mind that this is called in the very early stages of initialisation
* in order to get the virtual address of the serial port for the console...
*/
diff -u --recursive --new-file pre1/linux/drivers/hotplug/cpqphp_core.c linux/drivers/hotplug/cpqphp_core.c
--- pre1/linux/drivers/hotplug/cpqphp_core.c Fri Nov 9 14:01:21 2001
+++ linux/drivers/hotplug/cpqphp_core.c Thu Jan 17 14:06:53 2002
@@ -404,6 +404,10 @@
result = pci_hp_register (new_slot->hotplug_slot);
if (result) {
err ("pci_hp_register failed with error %d\n", result);
+ kfree (new_slot->hotplug_slot->info);
+ kfree (new_slot->hotplug_slot->name);
+ kfree (new_slot->hotplug_slot);
+ kfree (new_slot);
return result;
}
@@ -429,6 +433,8 @@
while (old_slot) {
next_slot = old_slot->next;
pci_hp_deregister (old_slot->hotplug_slot);
+ kfree(old_slot->hotplug_slot->info);
+ kfree(old_slot->hotplug_slot->name);
kfree(old_slot->hotplug_slot);
kfree(old_slot);
old_slot = next_slot;
diff -u --recursive --new-file pre1/linux/drivers/i2c/i2c-algo-bit.c linux/drivers/i2c/i2c-algo-bit.c
--- pre1/linux/drivers/i2c/i2c-algo-bit.c Thu Oct 11 08:05:47 2001
+++ linux/drivers/i2c/i2c-algo-bit.c Tue Jan 15 13:53:51 2002
@@ -50,7 +50,7 @@
/* might not like this, as they have an internal timeout of some mils */
/*
#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
- if (need_resched) schedule();
+ cond_resched();
*/
@@ -120,8 +120,7 @@
if (start+adap->timeout <= jiffies) {
return -ETIMEDOUT;
}
- if (current->need_resched)
- schedule();
+ cond_resched();
}
DEBSTAT(printk("needed %ld jiffies\n", jiffies-start));
#ifdef SLO_IO
diff -u --recursive --new-file pre1/linux/drivers/i2c/i2c-algo-ite.c linux/drivers/i2c/i2c-algo-ite.c
--- pre1/linux/drivers/i2c/i2c-algo-ite.c Thu Oct 11 08:05:47 2001
+++ linux/drivers/i2c/i2c-algo-ite.c Tue Jan 15 13:53:51 2002
@@ -67,7 +67,7 @@
/* might not like this, as they have an internal timeout of some mils */
/*
#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
- if (need_resched) schedule();
+ cond_resched();
*/
diff -u --recursive --new-file pre1/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- pre1/linux/drivers/ide/ide-disk.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/ide/ide-disk.c Thu Jan 17 13:58:35 2002
@@ -123,12 +123,10 @@
*/
static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
{
- if (rq_data_dir(rq) == READ)
- goto good_command;
- if (rq_data_dir(rq) == WRITE)
+ if (rq->flags & REQ_CMD)
goto good_command;
- printk(KERN_ERR "%s: bad command: %lx\n", drive->name, rq->flags);
+ blk_dump_rq_flags(rq, "do_rw_disk, bad command");
ide_end_request(0, HWGROUP(drive));
return ide_stopped;
@@ -179,8 +177,10 @@
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
ide_task_t args;
+ int sectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
+
unsigned int track = (block / drive->sect);
unsigned int sect = (block % drive->sect) + 1;
unsigned int head = (track % drive->head);
@@ -189,7 +189,16 @@
memset(&taskfile, 0, sizeof(task_struct_t));
memset(&hobfile, 0, sizeof(hob_struct_t));
- taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors;
+ sectors = rq->nr_sectors;
+ if (sectors == 256)
+ sectors = 0;
+ if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
+ sectors = drive->mult_count;
+ if (sectors > rq->current_nr_sectors)
+ sectors = rq->current_nr_sectors;
+ }
+
+ taskfile.sector_count = sectors;
taskfile.sector_number = sect;
taskfile.low_cylinder = cyl;
taskfile.high_cylinder = (cyl>>8);
@@ -225,13 +234,23 @@
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
ide_task_t args;
+ int sectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
+ sectors = rq->nr_sectors;
+ if (sectors == 256)
+ sectors = 0;
+ if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
+ sectors = drive->mult_count;
+ if (sectors > rq->current_nr_sectors)
+ sectors = rq->current_nr_sectors;
+ }
+
memset(&taskfile, 0, sizeof(task_struct_t));
memset(&hobfile, 0, sizeof(hob_struct_t));
- taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors;
+ taskfile.sector_count = sectors;
taskfile.sector_number = block;
taskfile.low_cylinder = (block>>=8);
taskfile.high_cylinder = (block>>=8);
@@ -273,14 +292,24 @@
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
ide_task_t args;
+ int sectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
memset(&taskfile, 0, sizeof(task_struct_t));
memset(&hobfile, 0, sizeof(hob_struct_t));
- taskfile.sector_count = rq->nr_sectors;
- hobfile.sector_count = (rq->nr_sectors>>8);
+ sectors = rq->nr_sectors;
+ if (sectors == 256)
+ sectors = 0;
+ if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
+ sectors = drive->mult_count;
+ if (sectors > rq->current_nr_sectors)
+ sectors = rq->current_nr_sectors;
+ }
+
+ taskfile.sector_count = sectors;
+ hobfile.sector_count = sectors >> 8;
if (rq->nr_sectors == 65536) {
taskfile.sector_count = 0x00;
@@ -652,7 +681,7 @@
memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
taskfile.sector_count = drive->mult_req;
taskfile.command = WIN_SETMULT;
- do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
+ do_taskfile(drive, &taskfile, &hobfile, &set_multmode_intr);
}
} else if (s->all) {
int special = s->all;
@@ -789,23 +818,12 @@
#endif /* CONFIG_PROC_FS */
+/*
+ * This is tightly woven into the driver->do_special can not touch.
+ * DON'T do it again until a total personality rewrite is committed.
+ */
static int set_multcount(ide_drive_t *drive, int arg)
{
-#if 1
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
-
- if (drive->special.b.set_multmode)
- return -EBUSY;
-
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.sector_count = drive->mult_req;
- taskfile.command = WIN_SETMULT;
- drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
- ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-#else
struct request rq;
if (drive->special.b.set_multmode)
@@ -814,7 +832,6 @@
drive->mult_req = arg;
drive->special.b.set_multmode = 1;
(void) ide_do_drive_cmd (drive, &rq, ide_wait);
-#endif
return (drive->mult_count == arg) ? 0 : -EIO;
}
diff -u --recursive --new-file pre1/linux/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- pre1/linux/drivers/ide/ide-floppy.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/ide/ide-floppy.c Tue Jan 15 12:32:36 2002
@@ -688,7 +688,7 @@
/* Why does this happen? */
if (!rq)
return;
- if (rq->flags & IDEFLOPPY_RQ) {
+ if (!(rq->flags & IDEFLOPPY_RQ)) {
ide_end_request (uptodate, hwgroup);
return;
}
diff -u --recursive --new-file pre1/linux/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- pre1/linux/drivers/ide/ide-tape.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/ide/ide-tape.c Tue Jan 15 18:57:07 2002
@@ -721,7 +721,7 @@
int request_transfer; /* Bytes to transfer */
int actually_transferred; /* Bytes actually transferred */
int buffer_size; /* Size of our data buffer */
- struct buffer_head *bh;
+ struct bio *bio;
char *b_data;
int b_count;
byte *buffer; /* Data buffer */
@@ -805,7 +805,7 @@
*/
typedef struct idetape_stage_s {
struct request rq; /* The corresponding request */
- struct buffer_head *bh; /* The data buffers */
+ struct bio *bio; /* The data buffers */
struct idetape_stage_s *next; /* Pointer to the next stage */
os_aux_t *aux; /* OnStream aux ptr */
} idetape_stage_t;
@@ -929,7 +929,7 @@
int stage_size; /* Data buffer size (chosen based on the tape's recommendation */
idetape_stage_t *merge_stage;
int merge_stage_size;
- struct buffer_head *bh;
+ struct bio *bio;
char *b_data;
int b_count;
@@ -1013,7 +1013,7 @@
* Measures number of frames:
*
* 1. written/read to/from the driver pipeline (pipeline_head).
- * 2. written/read to/from the tape buffers (buffer_head).
+ * 2. written/read to/from the tape buffers (bio).
* 3. written/read by the tape to/from the media (tape_head).
*/
int pipeline_head;
@@ -1493,52 +1493,52 @@
static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
{
- struct buffer_head *bh = pc->bh;
+ struct bio *bio = pc->bio;
int count;
while (bcount) {
#if IDETAPE_DEBUG_BUGS
- if (bh == NULL) {
- printk (KERN_ERR "ide-tape: bh == NULL in idetape_input_buffers\n");
+ if (bio == NULL) {
+ printk (KERN_ERR "ide-tape: bio == NULL in idetape_input_buffers\n");
idetape_discard_data (drive, bcount);
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount);
- atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count);
+ count = IDE_MIN (bio->bi_size - pc->b_count, bcount);
+ atapi_input_bytes (drive, bio_data(bio) + pc->b_count, count);
bcount -= count;
- atomic_add(count, &bh->b_count);
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
+ pc->b_count += bio->bi_size;
+ if (pc->b_count == bio->bi_size) {
+ bio = bio->bi_next;
+ if (bio)
+ pc->b_count = 0;
}
}
- pc->bh = bh;
+ pc->bio = bio;
}
static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
{
- struct buffer_head *bh = pc->bh;
+ struct bio *bio = pc->bio;
int count;
while (bcount) {
#if IDETAPE_DEBUG_BUGS
- if (bh == NULL) {
- printk (KERN_ERR "ide-tape: bh == NULL in idetape_output_buffers\n");
+ if (bio == NULL) {
+ printk (KERN_ERR "ide-tape: bio == NULL in idetape_output_buffers\n");
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
count = IDE_MIN (pc->b_count, bcount);
- atapi_output_bytes (drive, pc->b_data, count);
+ atapi_output_bytes (drive, bio_data(bio), count);
bcount -= count;
pc->b_data += count;
pc->b_count -= count;
if (!pc->b_count) {
- pc->bh = bh = bh->b_reqnext;
- if (bh) {
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
+ pc->bio = bio = bio->bi_next;
+ if (bio) {
+ pc->b_data = bio_data(bio);
+ pc->b_count = bio->bi_size;
}
}
}
@@ -1547,25 +1547,25 @@
#ifdef CONFIG_BLK_DEV_IDEDMA
static void idetape_update_buffers (idetape_pc_t *pc)
{
- struct buffer_head *bh = pc->bh;
+ struct bio *bio = pc->bio;
int count, bcount = pc->actually_transferred;
if (test_bit (PC_WRITING, &pc->flags))
return;
while (bcount) {
#if IDETAPE_DEBUG_BUGS
- if (bh == NULL) {
- printk (KERN_ERR "ide-tape: bh == NULL in idetape_update_buffers\n");
+ if (bio == NULL) {
+ printk (KERN_ERR "ide-tape: bio == NULL in idetape_update_buffers\n");
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bh->b_size, bcount);
- atomic_set(&bh->b_count, count);
- if (atomic_read(&bh->b_count) == bh->b_size)
- bh = bh->b_reqnext;
+ count = IDE_MIN (bio->bi_size, bcount);
+ pc->b_count = count;
+ if (pc->b_count == bio->bi_size)
+ bio = bio->bi_next;
bcount -= count;
}
- pc->bh = bh;
+ pc->bio = bio;
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -1625,7 +1625,7 @@
pc->request_transfer = 0;
pc->buffer = pc->pc_buffer;
pc->buffer_size = IDETAPE_PC_BUFFER_SIZE;
- pc->bh = NULL;
+ pc->bio = NULL;
pc->b_data = NULL;
}
@@ -1706,10 +1706,10 @@
printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
#endif
while (stage) {
- if (stage->rq.cmd == IDETAPE_WRITE_RQ)
- stage->rq.cmd = IDETAPE_ABORTED_WRITE_RQ;
- else if (stage->rq.cmd == IDETAPE_READ_RQ)
- stage->rq.cmd = IDETAPE_ABORTED_READ_RQ;
+ if (stage->rq.flags == IDETAPE_WRITE_RQ)
+ stage->rq.flags = IDETAPE_ABORTED_WRITE_RQ;
+ else if (stage->rq.flags == IDETAPE_READ_RQ)
+ stage->rq.flags = IDETAPE_ABORTED_READ_RQ;
stage = stage->next;
}
}
@@ -1735,7 +1735,7 @@
#endif /* IDETAPE_DEBUG_BUGS */
rq->buffer = NULL;
- rq->bh = stage->bh;
+ rq->bio = stage->bio;
tape->active_data_request = rq;
tape->active_stage = stage;
tape->next_stage = stage->next;
@@ -1769,21 +1769,21 @@
*/
static void __idetape_kfree_stage (idetape_stage_t *stage)
{
- struct buffer_head *prev_bh, *bh = stage->bh;
+ struct bio *prev_bio, *bio = stage->bio;
int size;
- while (bh != NULL) {
- if (bh->b_data != NULL) {
- size = (int) bh->b_size;
+ while (bio != NULL) {
+ if (bio_data(bio) != NULL) {
+ size = (int) bio->bi_size;
while (size > 0) {
- free_page ((unsigned long) bh->b_data);
+ free_page ((unsigned long) bio_data(bio));
size -= PAGE_SIZE;
- bh->b_data += PAGE_SIZE;
+ bio->bi_size += PAGE_SIZE;
}
}
- prev_bh = bh;
- bh = bh->b_reqnext;
- kfree (prev_bh);
+ prev_bio = bio;
+ bio = bio->bi_next;
+ kfree (prev_bio);
}
kfree (stage);
}
@@ -1868,13 +1868,13 @@
tape->active_stage = NULL;
tape->active_data_request = NULL;
tape->nr_pending_stages--;
- if (rq->cmd == IDETAPE_WRITE_RQ) {
+ if (rq->flags == IDETAPE_WRITE_RQ) {
#if ONSTREAM_DEBUG
if (tape->debug_level >= 2) {
if (tape->onstream) {
stage = tape->first_stage;
aux = stage->aux;
- p = stage->bh->b_data;
+ p = bio_data(stage->bio);
if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100)
printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++);
}
@@ -1908,7 +1908,7 @@
complete(tape->waiting);
}
}
- } else if (rq->cmd == IDETAPE_READ_RQ) {
+ } else if (rq->flags == IDETAPE_READ_RQ) {
if (error == IDETAPE_ERROR_EOD) {
set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
idetape_abort_pipeline(drive);
@@ -1984,7 +1984,7 @@
{
ide_init_drive_cmd (rq);
rq->buffer = (char *) pc;
- rq->cmd = IDETAPE_PC_RQ1;
+ rq->flags = IDETAPE_PC_RQ1;
(void) ide_do_drive_cmd (drive, rq, ide_preempt);
}
@@ -2164,12 +2164,12 @@
}
}
if (test_bit (PC_WRITING, &pc->flags)) {
- if (pc->bh != NULL)
+ if (pc->bio != NULL)
idetape_output_buffers (drive, pc, bcount.all);
else
atapi_output_bytes (drive,pc->current_position,bcount.all); /* Write the current buffer */
} else {
- if (pc->bh != NULL)
+ if (pc->bio != NULL)
idetape_input_buffers (drive, pc, bcount.all);
else
atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */
@@ -2523,21 +2523,22 @@
return ide_stopped;
}
-static void idetape_create_read_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh)
+static void idetape_create_read_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct bio *bio)
{
- struct buffer_head *p = bh;
+ struct bio *p = bio;
+ struct bio_vec *bv = bio_iovec(p);
idetape_init_pc (pc);
pc->c[0] = IDETAPE_READ_CMD;
put_unaligned (htonl (length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
pc->callback = &idetape_rw_callback;
- pc->bh = bh;
- atomic_set(&bh->b_count, 0);
+ pc->bio = bio;
+ bv->bv_len = 0;
pc->buffer = NULL;
if (tape->onstream) {
while (p) {
- atomic_set(&p->b_count, 0);
- p = p->b_reqnext;
+ bv->bv_len = 0;
+ p = p->bi_next;
}
}
if (!tape->onstream) {
@@ -2553,30 +2554,31 @@
}
}
-static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh)
+static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct bio *bio)
{
int size = 32768;
- struct buffer_head *p = bh;
+ struct bio *p = bio;
idetape_init_pc (pc);
pc->c[0] = IDETAPE_READ_BUFFER_CMD;
pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK;
pc->c[7] = size >> 8;
pc->c[8] = size & 0xff;
pc->callback = &idetape_pc_callback;
- pc->bh = bh;
- atomic_set(&bh->b_count, 0);
+ pc->bio = bio;
+ atomic_set(&bio->bi_cnt, 0);
pc->buffer = NULL;
while (p) {
- atomic_set(&p->b_count, 0);
- p = p->b_reqnext;
+ p->bi_size = 0;
+ p = p->bi_next;
}
pc->request_transfer = pc->buffer_size = size;
}
-static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh)
+static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct bio *bio)
{
- struct buffer_head *p = bh;
+ struct bio *p = bio;
+ struct bio_vec *bv= bio_iovec(p);
idetape_init_pc (pc);
pc->c[0] = IDETAPE_WRITE_CMD;
put_unaligned (htonl (length), (unsigned int *) &pc->c[1]);
@@ -2585,13 +2587,13 @@
set_bit (PC_WRITING, &pc->flags);
if (tape->onstream) {
while (p) {
- atomic_set(&p->b_count, p->b_size);
- p = p->b_reqnext;
+ bv->bv_len = p->bi_size;
+ p = p->bi_next;
}
}
- pc->bh = bh;
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
+ pc->bio = bio;
+ pc->b_data = bio_data(bio);
+ pc->b_count = bio->bi_size;
pc->buffer = NULL;
if (!tape->onstream) {
pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
@@ -2618,16 +2620,16 @@
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 5)
- printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
+/* printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %ld, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->flags,rq->errors); */
if (tape->debug_level >= 2)
- printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
+ printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
#endif /* IDETAPE_DEBUG_LOG */
- if (!IDETAPE_RQ_CMD (rq->cmd)) {
+ if (!IDETAPE_RQ_CMD (rq->flags)) {
/*
* We do not support buffer cache originated requests.
*/
- printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd);
+ printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags);
ide_end_request (0, HWGROUP (drive)); /* Let the common code handle it */
return ide_stopped;
}
@@ -2661,7 +2663,7 @@
*/
if (tape->onstream)
status.b.dsc = 1;
- if (!drive->dsc_overlap && rq->cmd != IDETAPE_PC_RQ2)
+ if (!drive->dsc_overlap && rq->flags != IDETAPE_PC_RQ2)
set_bit (IDETAPE_IGNORE_DSC, &tape->flags);
/*
@@ -2674,7 +2676,7 @@
*/
if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
tape->measure_insert_time = 1;
- if (tape->req_buffer_fill && (rq->cmd == IDETAPE_WRITE_RQ || rq->cmd == IDETAPE_READ_RQ)) {
+ if (tape->req_buffer_fill && (rq->flags == IDETAPE_WRITE_RQ || rq->flags == IDETAPE_READ_RQ)) {
tape->req_buffer_fill = 0;
tape->writes_since_buffer_fill = 0;
tape->reads_since_buffer_fill = 0;
@@ -2688,19 +2690,19 @@
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
calculate_speeds(drive);
if (tape->onstream && tape->max_frames &&
- ((rq->cmd == IDETAPE_WRITE_RQ &&
+ ((rq->flags == IDETAPE_WRITE_RQ &&
( tape->cur_frames == tape->max_frames ||
( tape->speed_control && tape->cur_frames > 5 &&
(tape->insert_speed > tape->max_insert_speed ||
(0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) ||
- (rq->cmd == IDETAPE_READ_RQ &&
+ (rq->flags == IDETAPE_READ_RQ &&
( tape->cur_frames == 0 ||
( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) &&
tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) {
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 4)
- printk(KERN_INFO "ide-tape: postponing request, cmd %d, cur %d, max %d\n",
- rq->cmd, tape->cur_frames, tape->max_frames);
+ printk(KERN_INFO "ide-tape: postponing request, cmd %ld, cur %d, max %d\n",
+ rq->flags, tape->cur_frames, tape->max_frames);
#endif
if (tape->postpone_cnt++ < 500) {
status.b.dsc = 0;
@@ -2718,7 +2720,7 @@
tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
} else if ((signed long) (jiffies - tape->dsc_timeout) > 0) {
printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name);
- if (rq->cmd == IDETAPE_PC_RQ2) {
+ if (rq->flags == IDETAPE_PC_RQ2) {
idetape_media_access_finished (drive);
return ide_stopped;
} else {
@@ -2729,7 +2731,7 @@
idetape_postpone_request (drive);
return ide_stopped;
}
- switch (rq->cmd) {
+ switch (rq->flags) {
case IDETAPE_READ_RQ:
tape->buffer_head++;
#if USE_IOTRACE
@@ -2744,7 +2746,7 @@
tape->req_buffer_fill = 1;
}
pc = idetape_next_pc_storage (drive);
- idetape_create_read_cmd (tape, pc, rq->current_nr_sectors, rq->bh);
+ idetape_create_read_cmd (tape, pc, rq->current_nr_sectors, rq->bio);
break;
case IDETAPE_WRITE_RQ:
tape->buffer_head++;
@@ -2761,15 +2763,15 @@
calculate_speeds(drive);
}
pc = idetape_next_pc_storage (drive);
- idetape_create_write_cmd (tape, pc, rq->current_nr_sectors, rq->bh);
+ idetape_create_write_cmd (tape, pc, rq->current_nr_sectors, rq->bio);
break;
case IDETAPE_READ_BUFFER_RQ:
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage (drive);
- idetape_create_read_buffer_cmd (tape, pc, rq->current_nr_sectors, rq->bh);
+ idetape_create_read_buffer_cmd (tape, pc, rq->current_nr_sectors, rq->bio);
break;
case IDETAPE_ABORTED_WRITE_RQ:
- rq->cmd = IDETAPE_WRITE_RQ;
+ rq->flags = IDETAPE_WRITE_RQ;
idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive));
return ide_stopped;
case IDETAPE_ABORTED_READ_RQ:
@@ -2777,12 +2779,12 @@
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name);
#endif
- rq->cmd = IDETAPE_READ_RQ;
+ rq->flags = IDETAPE_READ_RQ;
idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive));
return ide_stopped;
case IDETAPE_PC_RQ1:
pc = (idetape_pc_t *) rq->buffer;
- rq->cmd = IDETAPE_PC_RQ2;
+ rq->flags = IDETAPE_PC_RQ2;
break;
case IDETAPE_PC_RQ2:
idetape_media_access_finished (drive);
@@ -2822,61 +2824,65 @@
static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int clear)
{
idetape_stage_t *stage;
- struct buffer_head *prev_bh, *bh;
+ struct bio *prev_bio, *bio;
int pages = tape->pages_per_stage;
- char *b_data;
+ char *b_data = NULL;
+ struct bio_vec *bv;
if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
return NULL;
stage->next = NULL;
- bh = stage->bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL);
- if (bh == NULL)
+ bio = stage->bio = bio_alloc(GFP_KERNEL,1);
+ bv = bio_iovec(bio);
+ bv->bv_len = 0;
+ if (bio == NULL)
goto abort;
- bh->b_reqnext = NULL;
- if ((bh->b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
+ bio->bi_next = NULL;
+ if ((bio->bi_io_vec[0].bv_page = alloc_page(GFP_KERNEL)) == NULL)
goto abort;
if (clear)
- memset(bh->b_data, 0, PAGE_SIZE);
- bh->b_size = PAGE_SIZE;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
- set_bit (BH_Lock, &bh->b_state);
+ memset(bio_data(bio), 0, PAGE_SIZE);
+ bio->bi_size = PAGE_SIZE;
+ if(bv->bv_len == full) bv->bv_len = bio->bi_size;
+ set_bit (BH_Lock, &bio->bi_flags);
while (--pages) {
- if ((b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
+ if ((bio->bi_io_vec[pages].bv_page = alloc_page(GFP_KERNEL)) == NULL)
goto abort;
if (clear)
- memset(b_data, 0, PAGE_SIZE);
- if (bh->b_data == b_data + PAGE_SIZE) {
- bh->b_size += PAGE_SIZE;
- bh->b_data -= PAGE_SIZE;
+ memset(bio_data(bio), 0, PAGE_SIZE);
+ if (bio->bi_size == bv->bv_len + PAGE_SIZE) {
+ bio->bi_size += PAGE_SIZE;
+ bv->bv_len += PAGE_SIZE;
+ bv->bv_offset -= PAGE_SIZE;
if (full)
- atomic_add(PAGE_SIZE, &bh->b_count);
+ bio->bi_size += PAGE_SIZE;
continue;
}
- if (b_data == bh->b_data + bh->b_size) {
- bh->b_size += PAGE_SIZE;
+ if (b_data == bio_data(bio) + bio->bi_size) {
+ bio->bi_size += PAGE_SIZE;
if (full)
- atomic_add(PAGE_SIZE, &bh->b_count);
+ bio->bi_size += PAGE_SIZE;
continue;
}
- prev_bh = bh;
- if ((bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL)) == NULL) {
- free_page ((unsigned long) b_data);
+ prev_bio = bio;
+ if ((bio = bio_alloc(GFP_KERNEL,1)) == NULL) {
+ free_page ((unsigned long) bio_data(bio));
goto abort;
}
- bh->b_reqnext = NULL;
- bh->b_data = b_data;
- bh->b_size = PAGE_SIZE;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
- set_bit (BH_Lock, &bh->b_state);
- prev_bh->b_reqnext = bh;
+ bio->bi_next = NULL;
+ //bio->bi_io_vec[0].bv_offset = b_data;
+ bio->bi_size = PAGE_SIZE;
+ atomic_set(&bio->bi_cnt, full ? bio->bi_size : 0);
+ set_bit (BH_Lock, &bio->bi_flags);
+ prev_bio->bi_next = bio;
}
- bh->b_size -= tape->excess_bh_size;
+ bio->bi_size -= tape->excess_bh_size;
if (full)
- atomic_sub(tape->excess_bh_size, &bh->b_count);
+ atomic_sub(tape->excess_bh_size, &bio->bi_cnt);
if (tape->onstream)
- stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE);
+ stage->aux = (os_aux_t *) (bio_data(bio) + bio->bi_size - OS_AUX_SIZE);
return stage;
abort:
__idetape_kfree_stage (stage);
@@ -2903,39 +2909,39 @@
static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char *buf, int n)
{
- struct buffer_head *bh = tape->bh;
+ struct bio *bio = tape->bio;
int count;
while (n) {
#if IDETAPE_DEBUG_BUGS
- if (bh == NULL) {
- printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_from_user\n");
+ if (bio == NULL) {
+ printk (KERN_ERR "ide-tape: bio == NULL in idetape_copy_stage_from_user\n");
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n);
- copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count);
+ count = IDE_MIN (bio->bi_size - tape->b_count, n);
+ copy_from_user (bio_data(bio) + tape->b_count, buf, count);
n -= count;
- atomic_add(count, &bh->b_count);
+ bio->bi_size += count;
buf += count;
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
+ if (tape->b_count == bio->bi_size) {
+ bio = bio->bi_next;
+ if (bio)
+ tape->b_count = 0;
}
}
- tape->bh = bh;
+ tape->bio = bio;
}
static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape_stage_t *stage, int n)
{
- struct buffer_head *bh = tape->bh;
+ struct bio *bio = tape->bio;
int count;
while (n) {
#if IDETAPE_DEBUG_BUGS
- if (bh == NULL) {
- printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_to_user\n");
+ if (bio == NULL) {
+ printk (KERN_ERR "ide-tape: bio == NULL in idetape_copy_stage_to_user\n");
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
@@ -2946,10 +2952,10 @@
tape->b_count -= count;
buf += count;
if (!tape->b_count) {
- tape->bh = bh = bh->b_reqnext;
- if (bh) {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
+ tape->bio = bio = bio->bi_next;
+ if (bio) {
+ tape->b_data = bio_data(bio);
+ tape->b_count = bio->bi_size;
}
}
}
@@ -2957,25 +2963,25 @@
static void idetape_init_merge_stage (idetape_tape_t *tape)
{
- struct buffer_head *bh = tape->merge_stage->bh;
+ struct bio *bio = tape->merge_stage->bio;
- tape->bh = bh;
+ tape->bio = bio;
if (tape->chrdev_direction == idetape_direction_write)
- atomic_set(&bh->b_count, 0);
+ atomic_set(&bio->bi_cnt, 0);
else {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
+ tape->b_data = bio_data(bio);
+ tape->b_count = atomic_read(&bio->bi_cnt);
}
}
static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage)
{
- struct buffer_head *tmp;
+ struct bio *tmp;
os_aux_t *tmp_aux;
- tmp = stage->bh; tmp_aux = stage->aux;
- stage->bh = tape->merge_stage->bh; stage->aux = tape->merge_stage->aux;
- tape->merge_stage->bh = tmp; tape->merge_stage->aux = tmp_aux;
+ tmp = stage->bio; tmp_aux = stage->aux;
+ stage->bio = tape->merge_stage->bio; stage->aux = tape->merge_stage->aux;
+ tape->merge_stage->bio = tmp; tape->merge_stage->aux = tmp_aux;
idetape_init_merge_stage (tape);
}
@@ -3077,7 +3083,7 @@
idetape_tape_t *tape = drive->driver_data;
#if IDETAPE_DEBUG_BUGS
- if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) {
+ if (rq == NULL || !IDETAPE_RQ_CMD (rq->flags)) {
printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
return;
}
@@ -3185,7 +3191,7 @@
ide_init_drive_cmd (&rq);
rq.buffer = (char *) pc;
- rq.cmd = IDETAPE_PC_RQ1;
+ rq.flags = IDETAPE_PC_RQ1;
return ide_do_drive_cmd (drive, &rq, ide_wait);
}
@@ -3430,7 +3436,7 @@
* idetape_queue_rw_tail generates a read/write request for the block
* device interface and wait for it to be serviced.
*/
-static int idetape_queue_rw_tail (ide_drive_t *drive, int cmd, int blocks, struct buffer_head *bh)
+static int idetape_queue_rw_tail (ide_drive_t *drive, int cmd, int blocks, struct bio *bio)
{
idetape_tape_t *tape = drive->driver_data;
struct request rq;
@@ -3447,8 +3453,8 @@
#endif /* IDETAPE_DEBUG_BUGS */
ide_init_drive_cmd (&rq);
- rq.bh = bh;
- rq.cmd = cmd;
+ rq.bio = bio;
+ rq.flags = cmd;
rq.sector = tape->first_frame_position;
rq.nr_sectors = rq.current_nr_sectors = blocks;
if (tape->onstream)
@@ -3489,15 +3495,15 @@
if (!first)
first = stage;
aux = stage->aux;
- p = stage->bh->b_data;
- idetape_queue_rw_tail(drive, IDETAPE_READ_BUFFER_RQ, tape->capabilities.ctl, stage->bh);
+ p = bio_data(stage->bio);
+ idetape_queue_rw_tail(drive, IDETAPE_READ_BUFFER_RQ, tape->capabilities.ctl, stage->bio);
#if ONSTREAM_DEBUG
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++);
#endif
rq = &stage->rq;
ide_init_drive_cmd (rq);
- rq->cmd = IDETAPE_WRITE_RQ;
+ rq->flags = IDETAPE_WRITE_RQ;
rq->sector = tape->first_frame_position;
rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl;
idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++);
@@ -3646,18 +3652,18 @@
os_aux_t *aux = stage->aux;
os_partition_t *par = &aux->partition;
struct request *rq = &stage->rq;
- struct buffer_head *bh;
+ struct bio *bio;
if (!tape->onstream)
return 1;
if (tape->raw) {
if (rq->errors) {
- bh = stage->bh;
- while (bh) {
- memset(bh->b_data, 0, bh->b_size);
- bh = bh->b_reqnext;
+ bio = stage->bio;
+ while (bio) {
+ memset(bio_data(bio), 0, bio->bi_size);
+ bio = bio->bi_next;
}
- strcpy(stage->bh->b_data, "READ ERROR ON FRAME");
+ strcpy(bio_data(stage->bio), "READ ERROR ON FRAME");
}
return 1;
}
@@ -3767,12 +3773,12 @@
* Linux is short on memory. Fallback to
* non-pipelined operation mode for this request.
*/
- return idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh);
+ return idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bio);
}
}
rq = &new_stage->rq;
ide_init_drive_cmd (rq);
- rq->cmd = IDETAPE_WRITE_RQ;
+ rq->flags = IDETAPE_WRITE_RQ;
rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */
rq->nr_sectors = rq->current_nr_sectors = blocks;
@@ -3843,7 +3849,7 @@
{
idetape_tape_t *tape = drive->driver_data;
int blocks, i, min;
- struct buffer_head *bh;
+ struct bio *bio;
#if IDETAPE_DEBUG_BUGS
if (tape->chrdev_direction != idetape_direction_write) {
@@ -3860,22 +3866,22 @@
if (tape->merge_stage_size % tape->tape_block_size) {
blocks++;
i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size;
- bh = tape->bh->b_reqnext;
- while (bh) {
- atomic_set(&bh->b_count, 0);
- bh = bh->b_reqnext;
+ bio = tape->bio->bi_next;
+ while (bio) {
+ atomic_set(&bio->bi_cnt, 0);
+ bio = bio->bi_next;
}
- bh = tape->bh;
+ bio = tape->bio;
while (i) {
- if (bh == NULL) {
- printk(KERN_INFO "ide-tape: bug, bh NULL\n");
+ if (bio == NULL) {
+ printk(KERN_INFO "ide-tape: bug, bio NULL\n");
break;
}
- min = IDE_MIN(i, bh->b_size - atomic_read(&bh->b_count));
- memset(bh->b_data + atomic_read(&bh->b_count), 0, min);
- atomic_add(min, &bh->b_count);
+ min = IDE_MIN(i, bio->bi_size - atomic_read(&bio->bi_cnt));
+ memset(bio_data(bio) + bio->bi_size, 0, min);
+ atomic_add(min, &bio->bi_cnt);
i -= min;
- bh = bh->b_reqnext;
+ bio = bio->bi_next;
}
}
(void) idetape_add_chrdev_write_request (drive, blocks);
@@ -3949,7 +3955,7 @@
* is switched from completion mode to buffer available
* mode.
*/
- bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh);
+ bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bio);
if (bytes_read < 0) {
kfree (tape->merge_stage);
tape->merge_stage = NULL;
@@ -3960,7 +3966,7 @@
if (tape->restart_speed_control_req)
idetape_restart_speed_control(drive);
ide_init_drive_cmd (&rq);
- rq.cmd = IDETAPE_READ_RQ;
+ rq.flags = IDETAPE_READ_RQ;
rq.sector = tape->first_frame_position;
rq.nr_sectors = rq.current_nr_sectors = blocks;
if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) {
@@ -4083,7 +4089,7 @@
}
if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
return 0;
- return idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh);
+ return idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bio);
}
rq_ptr = &tape->first_stage->rq;
bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -4137,21 +4143,21 @@
static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
{
idetape_tape_t *tape = drive->driver_data;
- struct buffer_head *bh;
+ struct bio *bio;
int count, blocks;
while (bcount) {
- bh = tape->merge_stage->bh;
+ bio = tape->merge_stage->bio;
count = IDE_MIN (tape->stage_size, bcount);
bcount -= count;
blocks = count / tape->tape_block_size;
while (count) {
- atomic_set(&bh->b_count, IDE_MIN (count, bh->b_size));
- memset (bh->b_data, 0, atomic_read(&bh->b_count));
- count -= atomic_read(&bh->b_count);
- bh = bh->b_reqnext;
+ atomic_set(&bio->bi_cnt, IDE_MIN (count, bio->bi_size));
+ memset (bio_data(bio), 0, bio->bi_size);
+ count -= atomic_read(&bio->bi_cnt);
+ bio = bio->bi_next;
}
- idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh);
+ idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bio);
}
}
@@ -4276,7 +4282,7 @@
*/
static ide_drive_t *get_drive_ptr (kdev_t i_rdev)
{
- unsigned int i = MINOR(i_rdev) & ~0xc0;
+ unsigned int i = minor(i_rdev) & ~0xc0;
if (i >= MAX_HWIFS * MAX_DRIVES)
return NULL;
@@ -4654,7 +4660,7 @@
printk(KERN_INFO "ide-tape: current position (2) tape block %d\n", tape->last_frame_position);
#endif
idetape_position_tape(drive, last_mark_addr, 0, 0);
- if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) {
+ if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bio)) {
printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", tape->name);
__idetape_kfree_stage (stage);
idetape_position_tape(drive, position, 0, 0);
@@ -4673,7 +4679,7 @@
#endif
aux->next_mark_addr = htonl(next_mark_addr);
idetape_position_tape(drive, last_mark_addr, 0, 0);
- if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) {
+ if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) {
printk(KERN_INFO "ide-tape: %s: couldn't write back marker frame at %d\n", tape->name, last_mark_addr);
__idetape_kfree_stage (stage);
idetape_position_tape(drive, position, 0, 0);
@@ -4705,9 +4711,9 @@
if (rc != 0)
return; /* don't write fillers if we cannot position the tape. */
- strcpy(stage->bh->b_data, "Filler");
+ strcpy(bio_data(stage->bio), "Filler");
while (cnt--) {
- if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) {
+ if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) {
printk(KERN_INFO "ide-tape: %s: write_filler: couldn't write header frame\n", tape->name);
__idetape_kfree_stage (stage);
return;
@@ -4739,9 +4745,9 @@
header.partition.last_frame_addr = htonl(tape->capacity);
header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr);
header.partition.eod_frame_addr = htonl(tape->eod_frame_addr);
- memcpy(stage->bh->b_data, &header, sizeof(header));
+ memcpy(bio_data(stage->bio), &header, sizeof(header));
while (cnt--) {
- if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) {
+ if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bio)) {
printk(KERN_INFO "ide-tape: %s: couldn't write header frame\n", tape->name);
__idetape_kfree_stage (stage);
return;
@@ -4860,7 +4866,7 @@
* is switched from completion mode to buffer available
* mode.
*/
- retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh);
+ retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bio);
if (retval < 0) {
kfree (tape->merge_stage);
tape->merge_stage = NULL;
@@ -5326,12 +5332,12 @@
printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name);
#endif
idetape_position_tape(drive, block, 0, 0);
- if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) {
+ if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bio)) {
printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", tape->name);
__idetape_kfree_stage (stage);
return 0;
}
- header = (os_header_t *) stage->bh->b_data;
+ header = (os_header_t *) bio_data(stage->bio);
aux = stage->aux;
if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) {
printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name);
@@ -5403,7 +5409,7 @@
ide_drive_t *drive;
idetape_tape_t *tape;
idetape_pc_t pc;
- unsigned int minor=MINOR (inode->i_rdev);
+ unsigned int minor=minor(inode->i_rdev);
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
@@ -5460,7 +5466,7 @@
{
ide_drive_t *drive = get_drive_ptr (inode->i_rdev);
idetape_tape_t *tape = drive->driver_data;
- unsigned int minor=MINOR (inode->i_rdev);
+ unsigned int minor=minor(inode->i_rdev);
idetape_empty_write_pipeline (drive);
tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0);
@@ -5486,7 +5492,7 @@
ide_drive_t *drive = get_drive_ptr (inode->i_rdev);
idetape_tape_t *tape;
idetape_pc_t pc;
- unsigned int minor=MINOR (inode->i_rdev);
+ unsigned int minor=minor(inode->i_rdev);
tape = drive->driver_data;
#if IDETAPE_DEBUG_LOG
diff -u --recursive --new-file pre1/linux/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- pre1/linux/drivers/ide/ide-taskfile.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/ide/ide-taskfile.c Thu Jan 17 13:58:35 2002
@@ -706,8 +706,8 @@
ide__sti(); /* local CPU only */
if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */
-
+ return ide_error(drive, "task_no_data_intr", stat);
+ /* calls ide_end_drive_cmd */
if (args)
ide_end_drive_cmd (drive, stat, GET_ERR());
@@ -723,6 +723,7 @@
byte io_32bit = drive->io_32bit;
struct request *rq = HWGROUP(drive)->rq;
char *pBuf = NULL;
+ unsigned long flags;
if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT)) {
@@ -735,17 +736,21 @@
}
}
DTF("stat: %02x\n", stat);
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ pBuf = ide_map_rq(rq, &flags);
DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
drive->io_32bit = 0;
taskfile_input_data(drive, pBuf, SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
drive->io_32bit = io_32bit;
if (--rq->current_nr_sectors <= 0) {
/* (hs): swapped next 2 lines */
DTF("Request Ended stat: %02x\n", GET_STAT());
- ide_end_request(1, HWGROUP(drive));
+ if (ide_end_request(1, HWGROUP(drive))) {
+ ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL);
+ return ide_started;
+ }
} else {
ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL);
return ide_started;
@@ -809,13 +814,14 @@
byte io_32bit = drive->io_32bit;
struct request *rq = HWGROUP(drive)->rq;
char *pBuf = NULL;
+ unsigned long flags;
if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT)) {
return ide_error(drive, "task_mulin_intr", stat);
}
/* no data yet, so wait for another interrupt */
- ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL);
+ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
return ide_started;
}
@@ -834,10 +840,11 @@
*/
nsect = 1;
while (rq->current_nr_sectors) {
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ pBuf = ide_map_rq(rq, &flags);
DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
drive->io_32bit = 0;
taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
drive->io_32bit = io_32bit;
rq->errors = 0;
rq->current_nr_sectors -= nsect;
@@ -848,22 +855,34 @@
}
#endif /* ALTSTAT_SCREW_UP */
- nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ do {
+ nsect = rq->current_nr_sectors;
+ if (nsect > msect)
+ nsect = msect;
- DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
- pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- if (rq->current_nr_sectors != 0) {
- ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
+ pBuf = ide_map_rq(rq, &flags);
+
+ DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
+ pBuf, nsect, rq->current_nr_sectors);
+ drive->io_32bit = 0;
+ taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
+ drive->io_32bit = io_32bit;
+ rq->errors = 0;
+ rq->current_nr_sectors -= nsect;
+ msect -= nsect;
+ if (!rq->current_nr_sectors) {
+ if (!ide_end_request(1, HWGROUP(drive)))
+ return ide_stopped;
+ }
+ } while (msect);
+
+
+ /*
+ * more data left
+ */
+ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
+ return ide_started;
}
ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
@@ -879,10 +898,12 @@
/* (ks/hs): Fixed Multi Write */
if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) &&
(args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) {
+ unsigned long flags;
+ char *buf = ide_map_rq(rq, &flags);
/* For Write_sectors we need to stuff the first sector */
- taskfile_output_data(drive, rq->buffer, SECTOR_WORDS);
+ taskfile_output_data(drive, buf, SECTOR_WORDS);
rq->current_nr_sectors--;
- return ide_started;
+ ide_unmap_rq(rq, buf, &flags);
} else {
/*
* (ks/hs): Stuff the first sector(s)
@@ -913,8 +934,10 @@
byte io_32bit = drive->io_32bit;
struct request *rq = HWGROUP(drive)->rq;
char *pBuf = NULL;
+ unsigned long flags;
if (!rq->current_nr_sectors) {
+ printk("task_out_intr: should not trigger\n");
ide_end_request(1, HWGROUP(drive));
return ide_stopped;
}
@@ -922,19 +945,24 @@
if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
return ide_error(drive, "task_out_intr", stat);
}
+
if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
rq = HWGROUP(drive)->rq;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ pBuf = ide_map_rq(rq, &flags);
DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
drive->io_32bit = 0;
taskfile_output_data(drive, pBuf, SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
drive->io_32bit = io_32bit;
rq->errors = 0;
rq->current_nr_sectors--;
}
if (rq->current_nr_sectors <= 0) {
- ide_end_request(1, HWGROUP(drive));
+ if (ide_end_request(1, HWGROUP(drive))) {
+ ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
+ return ide_started;
+ }
} else {
ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
return ide_started;
@@ -961,14 +989,20 @@
struct request *rq = HWGROUP(drive)->rq;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
char *pBuf = NULL;
+ unsigned long flags;
/*
* (ks/hs): Handle last IRQ on multi-sector transfer,
- * occurs after all data was sent
+ * occurs after all data was sent in this chunk
*/
if (rq->current_nr_sectors == 0) {
if (stat & (ERR_STAT|DRQ_STAT))
return ide_error(drive, "task_mulout_intr", stat);
+
+ /*
+ * there may be more, ide_do_request will restart it if
+ * necessary
+ */
ide_end_request(1, HWGROUP(drive));
return ide_stopped;
}
@@ -994,10 +1028,11 @@
if (!msect) {
nsect = 1;
while (rq->current_nr_sectors) {
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ pBuf = ide_map_rq(rq, &flags);
DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
drive->io_32bit = 0;
taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(pBuf, &flags);
drive->io_32bit = io_32bit;
rq->errors = 0;
rq->current_nr_sectors -= nsect;
@@ -1008,12 +1043,16 @@
}
#endif /* ALTSTAT_SCREW_UP */
- nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
+ nsect = rq->current_nr_sectors;
+ if (nsect > msect)
+ nsect = msect;
+
+ pBuf = ide_map_rq(rq, &flags);
DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
pBuf, nsect, rq->current_nr_sectors);
drive->io_32bit = 0;
taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
drive->io_32bit = io_32bit;
rq->errors = 0;
rq->current_nr_sectors -= nsect;
diff -u --recursive --new-file pre1/linux/drivers/ide/ide.c linux/drivers/ide/ide.c
--- pre1/linux/drivers/ide/ide.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/ide/ide.c Thu Jan 17 13:58:35 2002
@@ -1458,14 +1458,11 @@
HWGROUP(drive)->rq = NULL;
rq->errors = 0;
- rq->sector = rq->bio->bi_sector;
- rq->current_nr_sectors = bio_sectors(rq->bio);
-
- /*
- * just to make sure...
- */
- if (rq->bio)
+ if (rq->bio) {
+ rq->sector = rq->bio->bi_sector;
+ rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
rq->buffer = NULL;
+ }
}
/*
diff -u --recursive --new-file pre1/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- pre1/linux/drivers/isdn/avmb1/b1pci.c Sun Jan 6 12:23:35 2002
+++ linux/drivers/isdn/avmb1/b1pci.c Thu Jan 17 14:04:15 2002
@@ -67,26 +67,6 @@
card->interrupt = 0;
}
-/* ------------------------------------------------------------- */
-
-static void b1pci_remove_ctr(struct capi_ctr *ctrl)
-{
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned int port = card->port;
-
- b1_reset(port);
- b1_reset(port);
-
- di->detach_ctr(ctrl);
- free_irq(card->irq, card);
- release_region(card->port, AVMB1_PORTLEN);
- ctrl->driverdata = 0;
- kfree(card->ctrlinfo);
- kfree(card);
-
- MOD_DEC_USE_COUNT;
-}
/* ------------------------------------------------------------- */
@@ -118,20 +98,18 @@
MOD_INC_USE_COUNT;
- card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
-
+ retval = -ENOMEM;
+ card = kmalloc(sizeof(avmcard), GFP_KERNEL);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err;
}
memset(card, 0, sizeof(avmcard));
- cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+
+ cinfo = kmalloc(sizeof(avmctrl_info), GFP_KERNEL);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_kfree;
}
memset(cinfo, 0, sizeof(avmctrl_info));
card->ctrlinfo = cinfo;
@@ -140,51 +118,38 @@
card->port = p->port;
card->irq = p->irq;
card->cardtype = avm_b1pci;
-
- if (check_region(card->port, AVMB1_PORTLEN)) {
+
+ if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ goto err_kfree_ctrlinfo;
}
b1_reset(card->port);
- if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
+ retval = b1_detect(card->port, card->cardtype);
+ if (retval) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
- driver->name, card->port, retval);
- kfree(card->ctrlinfo);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ driver->name, card->port, retval);
+ retval = -EIO;
+ goto err_release_region;
}
b1_reset(card->port);
b1_getrevision(card);
-
- request_region(p->port, AVMB1_PORTLEN, card->name);
-
+
retval = request_irq(card->irq, b1pci_interrupt, SA_SHIRQ, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
- driver->name, card->irq);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ driver->name, card->irq);
+ retval = -EBUSY;
+ goto err_release_region;
}
-
+
cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
if (!cinfo->capi_ctrl) {
printk(KERN_ERR "%s: attach controller failed.\n",
- driver->name);
- free_irq(card->irq, card);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ driver->name);
+ retval = -EBUSY;
+ goto err_free_irq;
}
if (card->revision >= 4) {
@@ -198,6 +163,37 @@
}
return 0;
+
+ err_free_irq:
+ free_irq(card->irq, card);
+ err_release_region:
+ release_region(card->port, AVMB1_PORTLEN);
+ err_kfree_ctrlinfo:
+ kfree(card->ctrlinfo);
+ err_kfree:
+ kfree(card);
+ err:
+ MOD_DEC_USE_COUNT;
+ return retval;
+}
+
+static void b1pci_remove_ctr(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ unsigned int port = card->port;
+
+ b1_reset(port);
+ b1_reset(port);
+
+ di->detach_ctr(ctrl);
+ free_irq(card->irq, card);
+ release_region(card->port, AVMB1_PORTLEN);
+ ctrl->driverdata = 0;
+ kfree(card->ctrlinfo);
+ kfree(card);
+
+ MOD_DEC_USE_COUNT;
}
/* ------------------------------------------------------------- */
@@ -226,25 +222,6 @@
/* ------------------------------------------------------------- */
-static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
-{
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
-
- b1dma_reset(card);
-
- div4->detach_ctr(ctrl);
- free_irq(card->irq, card);
- iounmap(card->mbase);
- release_region(card->port, AVMB1_PORTLEN);
- ctrl->driverdata = 0;
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
-
- MOD_DEC_USE_COUNT;
-}
-
static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
@@ -274,28 +251,23 @@
MOD_INC_USE_COUNT;
- card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
-
+ retval = -ENOMEM;
+ card = kmalloc(sizeof(avmcard), GFP_KERNEL);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err;
}
memset(card, 0, sizeof(avmcard));
+
card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
printk(KERN_WARNING "%s: dma alloc.\n", driver->name);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_kfree;
}
- cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+ cinfo = kmalloc(sizeof(avmctrl_info), GFP_KERNEL);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_dma_free;
}
memset(cinfo, 0, sizeof(avmctrl_info));
card->ctrlinfo = cinfo;
@@ -306,69 +278,47 @@
card->membase = p->membase;
card->cardtype = avm_b1pci;
- if (check_region(card->port, AVMB1_PORTLEN)) {
+ if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_kfree_ctrlinfo;
}
card->mbase = ioremap_nocache(card->membase, 64);
if (!card->mbase) {
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_release_region;
}
b1dma_reset(card);
- if ((retval = b1pciv4_detect(card)) != 0) {
+ retval = b1pciv4_detect(card);
+ if (retval) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval);
- iounmap(card->mbase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_unmap;
}
b1dma_reset(card);
b1_getrevision(card);
- request_region(p->port, AVMB1_PORTLEN, card->name);
-
retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
- iounmap(card->mbase);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_unmap;
}
cinfo->capi_ctrl = div4->attach_ctr(driver, card->name, cinfo);
if (!cinfo->capi_ctrl) {
printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
- iounmap(card->mbase);
- free_irq(card->irq, card);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_free_irq;
}
card->cardnr = cinfo->capi_ctrl->cnr;
@@ -378,6 +328,42 @@
card->membase, card->revision);
return 0;
+
+ err_free_irq:
+ free_irq(card->irq, card);
+ err_unmap:
+ iounmap(card->mbase);
+ err_release_region:
+ release_region(card->port, AVMB1_PORTLEN);
+ err_kfree_ctrlinfo:
+ kfree(card->ctrlinfo);
+ err_dma_free:
+ avmcard_dma_free(card->dma);
+ err_kfree:
+ kfree(card);
+ err:
+ MOD_DEC_USE_COUNT;
+ return retval;
+
+}
+
+static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+
+ b1dma_reset(card);
+
+ div4->detach_ctr(ctrl);
+ free_irq(card->irq, card);
+ iounmap(card->mbase);
+ release_region(card->port, AVMB1_PORTLEN);
+ ctrl->driverdata = 0;
+ kfree(card->ctrlinfo);
+ avmcard_dma_free(card->dma);
+ kfree(card);
+
+ MOD_DEC_USE_COUNT;
}
/* ------------------------------------------------------------- */
@@ -402,8 +388,6 @@
#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
-static int ncards = 0;
-
static int __devinit b1pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
@@ -470,6 +454,7 @@
struct capi_driver *driverv4 = &b1pciv4_driver;
#endif
char *p;
+ int ncards;
MOD_INC_USE_COUNT;
diff -u --recursive --new-file pre1/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c
--- pre1/linux/drivers/isdn/avmb1/c4.c Sun Jan 6 12:23:35 2002
+++ linux/drivers/isdn/avmb1/c4.c Thu Jan 17 14:04:15 2002
@@ -1133,28 +1133,23 @@
MOD_INC_USE_COUNT;
- card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
-
+ retval = -ENOMEM;
+ card = kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err;
}
memset(card, 0, sizeof(avmcard));
+
card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_kfree;
}
cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_dma_free;
}
memset(cinfo, 0, sizeof(avmctrl_info)*4);
card->ctrlinfo = cinfo;
@@ -1168,53 +1163,37 @@
card->membase = p->membase;
card->cardtype = nr == 4 ? avm_c4 : avm_c2;
- if (check_region(card->port, AVMB1_PORTLEN)) {
+ if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_kfree_ctrlinfo;
}
card->mbase = ioremap_nocache(card->membase, 128);
if (card->mbase == 0) {
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_release_region;
}
- if ((retval = c4_detect(card)) != 0) {
+ retval = c4_detect(card);
+ if (retval != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval);
- iounmap(card->mbase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_unmap;
}
c4_reset(card);
- request_region(p->port, AVMB1_PORTLEN, card->name);
-
retval = request_irq(card->irq, c4_interrupt, SA_SHIRQ, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
- iounmap(card->mbase);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_unmap;
}
for (i=0; i < nr ; i++) {
@@ -1228,14 +1207,7 @@
cinfo = &card->ctrlinfo[i];
di->detach_ctr(cinfo->capi_ctrl);
}
- iounmap(card->mbase);
- free_irq(card->irq, card);
- release_region(card->port, AVMB1_PORTLEN);
- avmcard_dma_free(card->dma);
- kfree(card->ctrlinfo);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ goto err_free_irq;
}
if (i == 0)
card->cardnr = cinfo->capi_ctrl->cnr;
@@ -1246,6 +1218,22 @@
driver->name, nr, card->port, card->irq, card->membase);
return 0;
+
+ err_free_irq:
+ free_irq(card->irq, card);
+ err_unmap:
+ iounmap(card->mbase);
+ err_release_region:
+ release_region(card->port, AVMB1_PORTLEN);
+ err_kfree_ctrlinfo:
+ kfree(card->ctrlinfo);
+ err_dma_free:
+ avmcard_dma_free(card->dma);
+ err_kfree:
+ kfree(card);
+ err:
+ MOD_DEC_USE_COUNT;
+ return retval;
}
/* ------------------------------------------------------------- */
diff -u --recursive --new-file pre1/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c
--- pre1/linux/drivers/isdn/avmb1/t1pci.c Sun Jan 6 12:23:35 2002
+++ linux/drivers/isdn/avmb1/t1pci.c Thu Jan 17 14:04:15 2002
@@ -49,27 +49,6 @@
/* ------------------------------------------------------------- */
-static void t1pci_remove_ctr(struct capi_ctr *ctrl)
-{
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
-
- b1dma_reset(card);
-
- di->detach_ctr(ctrl);
- free_irq(card->irq, card);
- iounmap(card->mbase);
- release_region(card->port, AVMB1_PORTLEN);
- ctrl->driverdata = 0;
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
-
- MOD_DEC_USE_COUNT;
-}
-
-/* ------------------------------------------------------------- */
-
static int t1pci_add_card(struct capi_driver *driver,
struct capicardparams *p,
struct pci_dev *dev)
@@ -80,28 +59,22 @@
MOD_INC_USE_COUNT;
- card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
-
+ retval = -ENOMEM;
+ card = kmalloc(sizeof(avmcard), GFP_KERNEL);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err;
}
memset(card, 0, sizeof(avmcard));
card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_kfree;
}
- cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+ cinfo = kmalloc(sizeof(avmctrl_info), GFP_KERNEL);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
+ goto err_dma_free;
}
memset(cinfo, 0, sizeof(avmctrl_info));
card->ctrlinfo = cinfo;
@@ -112,72 +85,50 @@
card->membase = p->membase;
card->cardtype = avm_t1pci;
- if (check_region(card->port, AVMB1_PORTLEN)) {
+ if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_kfree_ctrlinfo;
}
card->mbase = ioremap_nocache(card->membase, 64);
if (!card->mbase) {
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_release_region;
}
b1dma_reset(card);
- if ((retval = t1pci_detect(card)) != 0) {
+ retval = t1pci_detect(card);
+ if (retval != 0) {
if (retval < 6)
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval);
else
printk(KERN_NOTICE "%s: card at 0x%x, but cabel not connected or T1 has no power (%d)\n",
driver->name, card->port, retval);
- iounmap(card->mbase);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EIO;
+ retval = -EIO;
+ goto err_unmap;
}
b1dma_reset(card);
- request_region(p->port, AVMB1_PORTLEN, card->name);
-
retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
- iounmap(card->mbase);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_unmap;
}
cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
if (!cinfo->capi_ctrl) {
printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
- iounmap(card->mbase);
- free_irq(card->irq, card);
- release_region(card->port, AVMB1_PORTLEN);
- kfree(card->ctrlinfo);
- avmcard_dma_free(card->dma);
- kfree(card);
- MOD_DEC_USE_COUNT;
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_free_irq;
}
card->cardnr = cinfo->capi_ctrl->cnr;
@@ -186,6 +137,43 @@
driver->name, card->port, card->irq, card->membase);
return 0;
+
+ err_free_irq:
+ free_irq(card->irq, card);
+ err_unmap:
+ iounmap(card->mbase);
+ err_release_region:
+ release_region(card->port, AVMB1_PORTLEN);
+ err_kfree_ctrlinfo:
+ kfree(card->ctrlinfo);
+ err_dma_free:
+ avmcard_dma_free(card->dma);
+ err_kfree:
+ kfree(card);
+ err:
+ MOD_DEC_USE_COUNT;
+ return retval;
+}
+
+/* ------------------------------------------------------------- */
+
+static void t1pci_remove_ctr(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+
+ b1dma_reset(card);
+
+ di->detach_ctr(ctrl);
+ free_irq(card->irq, card);
+ iounmap(card->mbase);
+ release_region(card->port, AVMB1_PORTLEN);
+ ctrl->driverdata = 0;
+ kfree(card->ctrlinfo);
+ avmcard_dma_free(card->dma);
+ kfree(card);
+
+ MOD_DEC_USE_COUNT;
}
/* ------------------------------------------------------------- */
diff -u --recursive --new-file pre1/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- pre1/linux/drivers/isdn/isdn_common.c Thu Jan 3 12:20:10 2002
+++ linux/drivers/isdn/isdn_common.c Thu Jan 17 14:04:15 2002
@@ -65,7 +65,6 @@
#endif /* CONFIG_ISDN_DIVERSION */
-static int isdn_writebuf_stub(int, int, const u_char *, int, int);
static void set_global_features(void);
static void isdn_register_devfs(int);
static void isdn_unregister_devfs(int);
@@ -946,7 +945,9 @@
return istatbuf;
}
-/* Module interface-code */
+/*
+ * /dev/isdninfo
+ */
void
isdn_info_update(void)
@@ -960,234 +961,309 @@
wake_up_interruptible(&(dev->info_waitq));
}
+static int
+isdn_status_open(struct inode *ino, struct file *filep)
+{
+ infostruct *p;
+
+ p = kmalloc(sizeof(infostruct), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->next = (char *) dev->infochain;
+ p->private = (char *) &(filep->private_data);
+ dev->infochain = p;
+ /* At opening we allow a single update */
+ filep->private_data = (char *) 1;
+
+ return 0;
+}
+
+static int
+isdn_status_release(struct inode *ino, struct file *filep)
+{
+ infostruct *p = dev->infochain;
+ infostruct *q = NULL;
+
+ lock_kernel();
+
+ while (p) {
+ if (p->private == (char *) &(filep->private_data)) {
+ if (q)
+ q->next = p->next;
+ else
+ dev->infochain = (infostruct *) (p->next);
+ kfree(p);
+ goto out;
+ }
+ q = p;
+ p = (infostruct *) (p->next);
+ }
+ printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+
+ out:
+ unlock_kernel();
+ return 0;
+}
+
static ssize_t
-isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
+isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off)
{
- uint minor = minor(file->f_dentry->d_inode->i_rdev);
- int len = 0;
- ulong flags;
- int drvidx;
- int chidx;
int retval;
+ int len = 0;
char *p;
if (off != &file->f_pos)
return -ESPIPE;
lock_kernel();
- if (minor == ISDN_MINOR_STATUS) {
- if (!file->private_data) {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- goto out;
- }
- interruptible_sleep_on(&(dev->info_waitq));
- }
- p = isdn_statstr();
- file->private_data = 0;
- if ((len = strlen(p)) <= count) {
- if (copy_to_user(buf, p, len)) {
- retval = -EFAULT;
- goto out;
- }
- *off += len;
- retval = len;
+ if (!file->private_data) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
goto out;
}
- retval = 0;
- goto out;
- }
- if (!dev->drivers) {
- retval = -ENODEV;
- goto out;
+ interruptible_sleep_on(&(dev->info_waitq));
}
- if (minor <= ISDN_MINOR_BMAX) {
- printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0) {
- retval = -ENODEV;
- goto out;
- }
- if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
- retval = -ENODEV;
+ p = isdn_statstr();
+ file->private_data = 0;
+ if ((len = strlen(p)) <= count) {
+ if (copy_to_user(buf, p, len)) {
+ retval = -EFAULT;
goto out;
}
- chidx = isdn_minor2chan(minor);
- if (!(p = kmalloc(count, GFP_KERNEL))) {
- retval = -ENOMEM;
- goto out;
- }
- save_flags(flags);
- cli();
- len = isdn_readbchan(drvidx, chidx, p, 0, count,
- &dev->drv[drvidx]->rcv_waitq[chidx]);
- *off += len;
- restore_flags(flags);
- if (copy_to_user(buf,p,len))
- len = -EFAULT;
- kfree(p);
- retval = len;
- goto out;
- }
- if (minor <= ISDN_MINOR_CTRLMAX) {
- drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- if (drvidx < 0) {
- retval = -ENODEV;
- goto out;
- }
- if (!dev->drv[drvidx]->stavail) {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- goto out;
- }
- interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
- }
- if (dev->drv[drvidx]->interface->readstat) {
- if (count > dev->drv[drvidx]->stavail)
- count = dev->drv[drvidx]->stavail;
- len = dev->drv[drvidx]->interface->
- readstat(buf, count, 1, drvidx,
- isdn_minor2chan(minor));
- } else {
- len = 0;
- }
- save_flags(flags);
- cli();
- if (len)
- dev->drv[drvidx]->stavail -= len;
- else
- dev->drv[drvidx]->stavail = 0;
- restore_flags(flags);
*off += len;
retval = len;
goto out;
}
-#ifdef CONFIG_ISDN_PPP
- if (minor <= ISDN_MINOR_PPPMAX) {
- retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
- goto out;
- }
-#endif
- retval = -ENODEV;
+ retval = 0;
+ goto out;
+
out:
unlock_kernel();
return retval;
}
static ssize_t
-isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
+isdn_status_write(struct file *file, const char *buf, size_t count, loff_t *off)
+{
+ return -EPERM;
+}
+
+static unsigned int
+isdn_status_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ lock_kernel();
+
+ poll_wait(file, &(dev->info_waitq), wait);
+ if (file->private_data)
+ mask |= POLLIN | POLLRDNORM;
+
+ unlock_kernel();
+ return mask;
+}
+
+static int
+isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+ int ret;
+ union iocpar {
+ char name[10];
+ char bname[22];
+ isdn_ioctl_struct iocts;
+ isdn_net_ioctl_phone phone;
+ isdn_net_ioctl_cfg cfg;
+ } iocpar;
+
+#define name iocpar.name
+#define bname iocpar.bname
+#define iocts iocpar.iocts
+#define phone iocpar.phone
+#define cfg iocpar.cfg
+
+ switch (cmd) {
+ case IIOCGETDVR:
+ return (TTY_DV +
+ (NET_DV << 8) +
+ (INF_DV << 16));
+ case IIOCGETCPS:
+ if (arg) {
+ ulong *p = (ulong *) arg;
+ int i;
+ if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
+ return ret;
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ put_user(dev->ibytes[i], p++);
+ put_user(dev->obytes[i], p++);
+ }
+ return 0;
+ } else
+ return -EINVAL;
+ break;
+#ifdef CONFIG_NETDEVICES
+ case IIOCNETGPN:
+ /* Get peer phone number of a connected
+ * isdn network interface */
+ if (arg) {
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+ } else
+ return -EINVAL;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+#undef name
+#undef bname
+#undef iocts
+#undef phone
+#undef cfg
+}
+
+/*
+ * /dev/isdnctrlX
+ */
+
+static int
+isdn_ctrl_open(struct inode *ino, struct file *filep)
+{
+ uint minor = minor(ino->i_rdev);
+ int drvidx;
+
+ drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ if (drvidx < 0)
+ return -ENODEV;
+
+ isdn_lock_drivers();
+ return 0;
+}
+
+static int
+isdn_ctrl_release(struct inode *ino, struct file *filep)
+{
+ lock_kernel();
+
+ if (dev->profd == current)
+ dev->profd = NULL;
+
+ isdn_unlock_drivers();
+
+ unlock_kernel();
+ return 0;
+}
+
+static ssize_t
+isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off)
{
uint minor = minor(file->f_dentry->d_inode->i_rdev);
+ ulong flags;
+ int len = 0;
int drvidx;
- int chidx;
int retval;
if (off != &file->f_pos)
return -ESPIPE;
- if (minor == ISDN_MINOR_STATUS)
- return -EPERM;
- if (!dev->drivers)
- return -ENODEV;
-
lock_kernel();
- if (minor <= ISDN_MINOR_BMAX) {
- printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0) {
- retval = -ENODEV;
- goto out;
- }
- if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
- retval = -ENODEV;
- goto out;
- }
- chidx = isdn_minor2chan(minor);
- while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
- interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
- retval = count;
+
+ drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ if (drvidx < 0) {
+ retval = -ENODEV;
goto out;
}
- if (minor <= ISDN_MINOR_CTRLMAX) {
- drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- if (drvidx < 0) {
- retval = -ENODEV;
+ if (!dev->drv[drvidx]->stavail) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
goto out;
}
- /*
- * We want to use the isdnctrl device to load the firmware
- *
- if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
- return -ENODEV;
- */
- if (dev->drv[drvidx]->interface->writecmd)
- retval = dev->drv[drvidx]->interface->
- writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor));
- else
- retval = count;
- goto out;
+ interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
}
-#ifdef CONFIG_ISDN_PPP
- if (minor <= ISDN_MINOR_PPPMAX) {
- retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
- goto out;
+ if (dev->drv[drvidx]->interface->readstat) {
+ if (count > dev->drv[drvidx]->stavail)
+ count = dev->drv[drvidx]->stavail;
+ len = dev->drv[drvidx]->interface->
+ readstat(buf, count, 1, drvidx,
+ isdn_minor2chan(minor));
+ } else {
+ len = 0;
}
-#endif
- retval = -ENODEV;
+ save_flags(flags);
+ cli();
+ if (len)
+ dev->drv[drvidx]->stavail -= len;
+ else
+ dev->drv[drvidx]->stavail = 0;
+ restore_flags(flags);
+ *off += len;
+ retval = len;
+
out:
unlock_kernel();
return retval;
}
-static unsigned int
-isdn_poll(struct file *file, poll_table * wait)
+static ssize_t
+isdn_ctrl_write(struct file *file, const char *buf, size_t count, loff_t *off)
{
- unsigned int mask = 0;
- unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
- int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ uint minor = minor(file->f_dentry->d_inode->i_rdev);
+ int drvidx;
+ int retval;
+
+ if (off != &file->f_pos)
+ return -ESPIPE;
lock_kernel();
- if (minor == ISDN_MINOR_STATUS) {
- poll_wait(file, &(dev->info_waitq), wait);
- /* mask = POLLOUT | POLLWRNORM; */
- if (file->private_data) {
- mask |= POLLIN | POLLRDNORM;
- }
- goto out;
- }
- if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
- if (drvidx < 0) {
- /* driver deregistered while file open */
- mask = POLLHUP;
- goto out;
- }
- poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
- mask = POLLOUT | POLLWRNORM;
- if (dev->drv[drvidx]->stavail) {
- mask |= POLLIN | POLLRDNORM;
- }
+
+ drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ if (drvidx < 0) {
+ retval = -ENODEV;
goto out;
}
-#ifdef CONFIG_ISDN_PPP
- if (minor <= ISDN_MINOR_PPPMAX) {
- mask = isdn_ppp_poll(file, wait);
+ if (!dev->drv[drvidx]->interface->writecmd) {
+ retval = -EINVAL;
goto out;
}
-#endif
- mask = POLLERR;
+ retval = dev->drv[drvidx]->interface->
+ writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL));
+
out:
unlock_kernel();
+ return retval;
+}
+
+static unsigned int
+isdn_ctrl_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+ unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
+ int drvidx;
+
+ drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ if (drvidx < 0)
+ /* driver deregistered while file open */
+ return POLLHUP;
+
+ lock_kernel();
+
+ poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
+ mask = POLLOUT | POLLWRNORM;
+ if (dev->drv[drvidx]->stavail)
+ mask |= POLLIN | POLLRDNORM;
+
+ unlock_kernel();
return mask;
}
static int
-isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
{
- uint minor = minor(inode->i_rdev);
isdn_ctrl c;
int drvidx;
- int chidx;
int ret;
int i;
char *p;
@@ -1205,55 +1281,6 @@
#define iocts iocpar.iocts
#define phone iocpar.phone
#define cfg iocpar.cfg
-
- if (minor == ISDN_MINOR_STATUS) {
- switch (cmd) {
- case IIOCGETDVR:
- return (TTY_DV +
- (NET_DV << 8) +
- (INF_DV << 16));
- case IIOCGETCPS:
- if (arg) {
- ulong *p = (ulong *) arg;
- int i;
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
- return ret;
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- put_user(dev->ibytes[i], p++);
- put_user(dev->obytes[i], p++);
- }
- return 0;
- } else
- return -EINVAL;
- break;
-#ifdef CONFIG_NETDEVICES
- case IIOCNETGPN:
- /* Get peer phone number of a connected
- * isdn network interface */
- if (arg) {
- if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
- return -EFAULT;
- return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
- } else
- return -EINVAL;
-#endif
- default:
- return -EINVAL;
- }
- }
- if (!dev->drivers)
- return -ENODEV;
- if (minor <= ISDN_MINOR_BMAX) {
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0)
- return -ENODEV;
- chidx = isdn_minor2chan(minor);
- if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
- return -ENODEV;
- return 0;
- }
- if (minor <= ISDN_MINOR_CTRLMAX) {
/*
* isdn net devices manage lots of configuration variables as linked lists.
* Those lists must only be manipulated from user space. Some of the ioctl's
@@ -1261,366 +1288,360 @@
* manipulating the lists and ioctl's sleeping while accessing the lists
* are serialized by means of a semaphore.
*/
- switch (cmd) {
- case IIOCNETDWRSET:
- printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
- return(-EINVAL);
- case IIOCNETLCR:
- printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
- return -ENODEV;
+ switch (cmd) {
+ case IIOCNETDWRSET:
+ printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
+ return(-EINVAL);
+ case IIOCNETLCR:
+ printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
+ return -ENODEV;
#ifdef CONFIG_NETDEVICES
- case IIOCNETAIF:
- /* Add a network-interface */
- if (arg) {
- if (copy_from_user(name, (char *) arg, sizeof(name)))
- return -EFAULT;
- s = name;
- } else {
- s = NULL;
- }
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- if ((s = isdn_net_new(s, NULL))) {
- if (copy_to_user((char *) arg, s, strlen(s) + 1)){
- ret = -EFAULT;
- } else {
- ret = 0;
+ case IIOCNETAIF:
+ /* Add a network-interface */
+ if (arg) {
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ s = name;
+ } else {
+ s = NULL;
+ }
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ if ((s = isdn_net_new(s, NULL))) {
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
+ } else
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
+ case IIOCNETASL:
+ /* Add a slave to a network-interface */
+ if (arg) {
+ if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
+ return -EFAULT;
+ } else
+ return -EINVAL;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ if ((s = isdn_net_newslave(bname))) {
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
+ } else
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
+ case IIOCNETDIF:
+ /* Delete a network-interface */
+ if (arg) {
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_rm(name);
+ up(&dev->sem);
+ return ret;
+ } else
+ return -EINVAL;
+ case IIOCNETSCF:
+ /* Set configurable parameters of a network-interface */
+ if (arg) {
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
+ return isdn_net_setcfg(&cfg);
+ } else
+ return -EINVAL;
+ case IIOCNETGCF:
+ /* Get configurable parameters of a network-interface */
+ if (arg) {
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
+ if (!(ret = isdn_net_getcfg(&cfg))) {
+ if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+ return -EFAULT;
+ }
+ return ret;
+ } else
+ return -EINVAL;
+ case IIOCNETANM:
+ /* Add a phone-number to a network-interface */
+ if (arg) {
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_addphone(&phone);
+ up(&dev->sem);
+ return ret;
+ } else
+ return -EINVAL;
+ case IIOCNETGNM:
+ /* Get list of phone-numbers of a network-interface */
+ if (arg) {
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_getphones(&phone, (char *) arg);
+ up(&dev->sem);
+ return ret;
+ } else
+ return -EINVAL;
+ case IIOCNETDNM:
+ /* Delete a phone-number of a network-interface */
+ if (arg) {
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_delphone(&phone);
+ up(&dev->sem);
+ return ret;
+ } else
+ return -EINVAL;
+ case IIOCNETDIL:
+ /* Force dialing of a network-interface */
+ if (arg) {
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ return isdn_net_force_dial(name);
+ } else
+ return -EINVAL;
+#ifdef CONFIG_ISDN_PPP
+ case IIOCNETALN:
+ if (!arg)
+ return -EINVAL;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ return isdn_ppp_dial_slave(name);
+ case IIOCNETDLN:
+ if (!arg)
+ return -EINVAL;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ return isdn_ppp_hangup_slave(name);
+#endif
+ case IIOCNETHUP:
+ /* Force hangup of a network-interface */
+ if (!arg)
+ return -EINVAL;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ return isdn_net_force_hangup(name);
+ break;
+#endif /* CONFIG_NETDEVICES */
+ case IIOCSETVER:
+ dev->net_verbose = arg;
+ printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
+ return 0;
+ case IIOCSETGST:
+ if (arg)
+ dev->global_flags |= ISDN_GLOBAL_STOPPED;
+ else
+ dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
+ printk(KERN_INFO "isdn: Global Mode %s\n",
+ (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
+ return 0;
+ case IIOCSETBRJ:
+ drvidx = -1;
+ if (arg) {
+ int i;
+ char *p;
+ if (copy_from_user((char *) &iocts, (char *) arg,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
+ if (strlen(iocts.drvid)) {
+ if ((p = strchr(iocts.drvid, ',')))
+ *p = 0;
+ drvidx = -1;
+ for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+ if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+ drvidx = i;
+ break;
}
- } else
- ret = -ENODEV;
- up(&dev->sem);
+ }
+ }
+ if (drvidx == -1)
+ return -ENODEV;
+ if (iocts.arg)
+ dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
+ else
+ dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+ return 0;
+ case IIOCSIGPRF:
+ dev->profd = current;
+ return 0;
+ break;
+ case IIOCGETPRF:
+ /* Get all Modem-Profiles */
+ if (arg) {
+ char *p = (char *) arg;
+ int i;
+
+ if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+ (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+ * ISDN_MAX_CHANNELS)))
return ret;
- case IIOCNETASL:
- /* Add a slave to a network-interface */
- if (arg) {
- if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
- return -EFAULT;
- } else
- return -EINVAL;
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- if ((s = isdn_net_newslave(bname))) {
- if (copy_to_user((char *) arg, s, strlen(s) + 1)){
- ret = -EFAULT;
- } else {
- ret = 0;
- }
- } else
- ret = -ENODEV;
- up(&dev->sem);
+
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ if (copy_to_user(p, dev->mdm.info[i].emu.profile,
+ ISDN_MODEM_NUMREG))
+ return -EFAULT;
+ p += ISDN_MODEM_NUMREG;
+ if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
+ return -EFAULT;
+ p += ISDN_MSNLEN;
+ if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
+ return -EFAULT;
+ p += ISDN_LMSNLEN;
+ }
+ return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
+ } else
+ return -EINVAL;
+ break;
+ case IIOCSETPRF:
+ /* Set all Modem-Profiles */
+ if (arg) {
+ char *p = (char *) arg;
+ int i;
+
+ if ((ret = verify_area(VERIFY_READ, (void *) arg,
+ (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+ * ISDN_MAX_CHANNELS)))
return ret;
- case IIOCNETDIF:
- /* Delete a network-interface */
- if (arg) {
- if (copy_from_user(name, (char *) arg, sizeof(name)))
- return -EFAULT;
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- ret = isdn_net_rm(name);
- up(&dev->sem);
- return ret;
- } else
- return -EINVAL;
- case IIOCNETSCF:
- /* Set configurable parameters of a network-interface */
- if (arg) {
- if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
- return -EFAULT;
- return isdn_net_setcfg(&cfg);
- } else
- return -EINVAL;
- case IIOCNETGCF:
- /* Get configurable parameters of a network-interface */
- if (arg) {
- if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
- return -EFAULT;
- if (!(ret = isdn_net_getcfg(&cfg))) {
- if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
- return -EFAULT;
- }
- return ret;
- } else
- return -EINVAL;
- case IIOCNETANM:
- /* Add a phone-number to a network-interface */
- if (arg) {
- if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
- return -EFAULT;
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- ret = isdn_net_addphone(&phone);
- up(&dev->sem);
- return ret;
- } else
- return -EINVAL;
- case IIOCNETGNM:
- /* Get list of phone-numbers of a network-interface */
- if (arg) {
- if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
- return -EFAULT;
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- ret = isdn_net_getphones(&phone, (char *) arg);
- up(&dev->sem);
- return ret;
- } else
- return -EINVAL;
- case IIOCNETDNM:
- /* Delete a phone-number of a network-interface */
- if (arg) {
- if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
- return -EFAULT;
- ret = down_interruptible(&dev->sem);
- if( ret ) return ret;
- ret = isdn_net_delphone(&phone);
- up(&dev->sem);
- return ret;
- } else
- return -EINVAL;
- case IIOCNETDIL:
- /* Force dialing of a network-interface */
- if (arg) {
- if (copy_from_user(name, (char *) arg, sizeof(name)))
- return -EFAULT;
- return isdn_net_force_dial(name);
- } else
- return -EINVAL;
-#ifdef CONFIG_ISDN_PPP
- case IIOCNETALN:
- if (!arg)
- return -EINVAL;
- if (copy_from_user(name, (char *) arg, sizeof(name)))
+
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ if (copy_from_user(dev->mdm.info[i].emu.profile, p,
+ ISDN_MODEM_NUMREG))
return -EFAULT;
- return isdn_ppp_dial_slave(name);
- case IIOCNETDLN:
- if (!arg)
- return -EINVAL;
- if (copy_from_user(name, (char *) arg, sizeof(name)))
+ p += ISDN_MODEM_NUMREG;
+ if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
return -EFAULT;
- return isdn_ppp_hangup_slave(name);
-#endif
- case IIOCNETHUP:
- /* Force hangup of a network-interface */
- if (!arg)
- return -EINVAL;
- if (copy_from_user(name, (char *) arg, sizeof(name)))
+ p += ISDN_LMSNLEN;
+ if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
return -EFAULT;
- return isdn_net_force_hangup(name);
- break;
-#endif /* CONFIG_NETDEVICES */
- case IIOCSETVER:
- dev->net_verbose = arg;
- printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
- return 0;
- case IIOCSETGST:
- if (arg)
- dev->global_flags |= ISDN_GLOBAL_STOPPED;
- else
- dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
- printk(KERN_INFO "isdn: Global Mode %s\n",
- (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
- return 0;
- case IIOCSETBRJ:
+ p += ISDN_MSNLEN;
+ }
+ return 0;
+ } else
+ return -EINVAL;
+ break;
+ case IIOCSETMAP:
+ case IIOCGETMAP:
+ /* Set/Get MSN->EAZ-Mapping for a driver */
+ if (arg) {
+
+ if (copy_from_user((char *) &iocts,
+ (char *) arg,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
+ if (strlen(iocts.drvid)) {
drvidx = -1;
- if (arg) {
- int i;
- char *p;
- if (copy_from_user((char *) &iocts, (char *) arg,
- sizeof(isdn_ioctl_struct)))
- return -EFAULT;
- if (strlen(iocts.drvid)) {
- if ((p = strchr(iocts.drvid, ',')))
- *p = 0;
- drvidx = -1;
- for (i = 0; i < ISDN_MAX_DRIVERS; i++)
- if (!(strcmp(dev->drvid[i], iocts.drvid))) {
- drvidx = i;
- break;
- }
- }
- }
- if (drvidx == -1)
- return -ENODEV;
- if (iocts.arg)
- dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
- else
- dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
- return 0;
- case IIOCSIGPRF:
- dev->profd = current;
- return 0;
- break;
- case IIOCGETPRF:
- /* Get all Modem-Profiles */
- if (arg) {
- char *p = (char *) arg;
- int i;
-
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
-
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (copy_to_user(p, dev->mdm.info[i].emu.profile,
- ISDN_MODEM_NUMREG))
- return -EFAULT;
- p += ISDN_MODEM_NUMREG;
- if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
- return -EFAULT;
- p += ISDN_MSNLEN;
- if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
- return -EFAULT;
- p += ISDN_LMSNLEN;
- }
- return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
- } else
- return -EINVAL;
- break;
- case IIOCSETPRF:
- /* Set all Modem-Profiles */
- if (arg) {
- char *p = (char *) arg;
- int i;
-
- if ((ret = verify_area(VERIFY_READ, (void *) arg,
- (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
-
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (copy_from_user(dev->mdm.info[i].emu.profile, p,
- ISDN_MODEM_NUMREG))
- return -EFAULT;
- p += ISDN_MODEM_NUMREG;
- if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
- return -EFAULT;
- p += ISDN_LMSNLEN;
- if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
- return -EFAULT;
- p += ISDN_MSNLEN;
+ for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+ if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+ drvidx = i;
+ break;
}
- return 0;
- } else
- return -EINVAL;
- break;
- case IIOCSETMAP:
- case IIOCGETMAP:
- /* Set/Get MSN->EAZ-Mapping for a driver */
- if (arg) {
-
- if (copy_from_user((char *) &iocts,
- (char *) arg,
- sizeof(isdn_ioctl_struct)))
- return -EFAULT;
- if (strlen(iocts.drvid)) {
- drvidx = -1;
- for (i = 0; i < ISDN_MAX_DRIVERS; i++)
- if (!(strcmp(dev->drvid[i], iocts.drvid))) {
- drvidx = i;
- break;
- }
- } else
- drvidx = 0;
- if (drvidx == -1)
- return -ENODEV;
- if (cmd == IIOCSETMAP) {
- int loop = 1;
-
- p = (char *) iocts.arg;
- i = 0;
- while (loop) {
- int j = 0;
-
- while (1) {
- if ((ret = verify_area(VERIFY_READ, p, 1)))
- return ret;
- get_user(bname[j], p++);
- switch (bname[j]) {
- case '\0':
- loop = 0;
- /* Fall through */
- case ',':
- bname[j] = '\0';
- strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
- j = ISDN_MSNLEN;
- break;
- default:
- j++;
- }
- if (j >= ISDN_MSNLEN)
- break;
- }
- if (++i > 9)
- break;
- }
- } else {
- p = (char *) iocts.arg;
- for (i = 0; i < 10; i++) {
- sprintf(bname, "%s%s",
- strlen(dev->drv[drvidx]->msn2eaz[i]) ?
- dev->drv[drvidx]->msn2eaz[i] : "_",
- (i < 9) ? "," : "\0");
- if (copy_to_user(p, bname, strlen(bname) + 1))
- return -EFAULT;
- p += strlen(bname);
+ } else
+ drvidx = 0;
+ if (drvidx == -1)
+ return -ENODEV;
+ if (cmd == IIOCSETMAP) {
+ int loop = 1;
+
+ p = (char *) iocts.arg;
+ i = 0;
+ while (loop) {
+ int j = 0;
+
+ while (1) {
+ if ((ret = verify_area(VERIFY_READ, p, 1)))
+ return ret;
+ get_user(bname[j], p++);
+ switch (bname[j]) {
+ case '\0':
+ loop = 0;
+ /* Fall through */
+ case ',':
+ bname[j] = '\0';
+ strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
+ j = ISDN_MSNLEN;
+ break;
+ default:
+ j++;
}
+ if (j >= ISDN_MSNLEN)
+ break;
}
- return 0;
- } else
- return -EINVAL;
- case IIOCDBGVAR:
- if (arg) {
- if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
- return -EFAULT;
- return 0;
- } else
- return -EINVAL;
- break;
- default:
- if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
- cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
- else
- return -EINVAL;
- if (arg) {
- int i;
- char *p;
- if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
- return -EFAULT;
- if (strlen(iocts.drvid)) {
- if ((p = strchr(iocts.drvid, ',')))
- *p = 0;
- drvidx = -1;
- for (i = 0; i < ISDN_MAX_DRIVERS; i++)
- if (!(strcmp(dev->drvid[i], iocts.drvid))) {
- drvidx = i;
- break;
- }
- } else
- drvidx = 0;
- if (drvidx == -1)
- return -ENODEV;
- if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
- c.driver = drvidx;
- c.command = ISDN_CMD_IOCTL;
- c.arg = cmd;
- memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
- ret = isdn_command(&c);
- memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
- if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
+ if (++i > 9)
+ break;
+ }
+ } else {
+ p = (char *) iocts.arg;
+ for (i = 0; i < 10; i++) {
+ sprintf(bname, "%s%s",
+ strlen(dev->drv[drvidx]->msn2eaz[i]) ?
+ dev->drv[drvidx]->msn2eaz[i] : "_",
+ (i < 9) ? "," : "\0");
+ if (copy_to_user(p, bname, strlen(bname) + 1))
return -EFAULT;
- return ret;
- } else
- return -EINVAL;
- }
+ p += strlen(bname);
+ }
+ }
+ return 0;
+ } else
+ return -EINVAL;
+ case IIOCDBGVAR:
+ if (arg) {
+ if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
+ return -EFAULT;
+ return 0;
+ } else
+ return -EINVAL;
+ break;
+ default:
+ if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
+ cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
+ else
+ return -EINVAL;
+ if (arg) {
+ int i;
+ char *p;
+ if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
+ if (strlen(iocts.drvid)) {
+ if ((p = strchr(iocts.drvid, ',')))
+ *p = 0;
+ drvidx = -1;
+ for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+ if (!(strcmp(dev->drvid[i], iocts.drvid))) {
+ drvidx = i;
+ break;
+ }
+ } else
+ drvidx = 0;
+ if (drvidx == -1)
+ return -ENODEV;
+ if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(isdn_ioctl_struct))))
+ return ret;
+ c.driver = drvidx;
+ c.command = ISDN_CMD_IOCTL;
+ c.arg = cmd;
+ memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
+ ret = isdn_command(&c);
+ memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
+ if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
+ return ret;
+ } else
+ return -EINVAL;
}
-#ifdef CONFIG_ISDN_PPP
- if (minor <= ISDN_MINOR_PPPMAX)
- return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
-#endif
- return -ENODEV;
#undef name
#undef bname
@@ -1630,67 +1651,120 @@
}
/*
+ *
+ */
+
+static ssize_t
+isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
+{
+ uint minor = minor(file->f_dentry->d_inode->i_rdev);
+
+ if (minor < ISDN_MINOR_CTRL)
+ return -ENODEV;
+
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_read(file, buf, count, off);
+
+#ifdef CONFIG_ISDN_PPP
+ if (minor <= ISDN_MINOR_PPPMAX)
+ return isdn_ppp_read(file, buf, count, off);
+#endif
+
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_read(file, buf, count, off);
+
+ return -ENODEV;
+}
+
+static ssize_t
+isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
+{
+ uint minor = minor(file->f_dentry->d_inode->i_rdev);
+
+ if (minor < ISDN_MINOR_CTRL)
+ return -ENODEV;
+
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_write(file, buf, count, off);
+
+#ifdef CONFIG_ISDN_PPP
+ if (minor <= ISDN_MINOR_PPPMAX)
+ return isdn_ppp_write(file, buf, count, off);
+#endif
+
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_write(file, buf, count, off);
+
+ return -ENODEV;
+}
+
+static unsigned int
+isdn_poll(struct file *file, poll_table * wait)
+{
+ unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
+
+ if (minor < ISDN_MINOR_CTRL)
+ return POLLERR;
+
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_poll(file, wait);
+
+#ifdef CONFIG_ISDN_PPP
+ if (minor <= ISDN_MINOR_PPPMAX)
+ return isdn_ppp_poll(file, wait);
+#endif
+
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_poll(file, wait);
+
+ return POLLERR;
+}
+
+static int
+isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+ uint minor = minor(inode->i_rdev);
+
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_ioctl(inode, file, cmd, arg);
+
+ if (minor < ISDN_MINOR_CTRL)
+ return -ENODEV;
+
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_ioctl(inode, file, cmd, arg);
+
+#ifdef CONFIG_ISDN_PPP
+ if (minor <= ISDN_MINOR_PPPMAX)
+ return isdn_ppp_ioctl(inode, file, cmd, arg);
+#endif
+
+ return -ENODEV;
+}
+
+/*
* Open the device code.
*/
static int
isdn_open(struct inode *ino, struct file *filep)
{
uint minor = minor(ino->i_rdev);
- int drvidx;
- int chidx;
- int retval = -ENODEV;
+ if (minor < ISDN_MINOR_CTRL)
+ return -ENODEV;
- if (minor == ISDN_MINOR_STATUS) {
- infostruct *p;
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_open(ino, filep);
+
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_open(ino, filep);
- if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
- p->next = (char *) dev->infochain;
- p->private = (char *) &(filep->private_data);
- dev->infochain = p;
- /* At opening we allow a single update */
- filep->private_data = (char *) 1;
- retval = 0;
- goto out;
- } else {
- retval = -ENOMEM;
- goto out;
- }
- }
- if (!dev->channels)
- goto out;
- if (minor <= ISDN_MINOR_BMAX) {
- printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0)
- goto out;
- chidx = isdn_minor2chan(minor);
- if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
- goto out;
- if (!(dev->drv[drvidx]->online & (1 << chidx)))
- goto out;
- isdn_lock_drivers();
- retval = 0;
- goto out;
- }
- if (minor <= ISDN_MINOR_CTRLMAX) {
- drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- if (drvidx < 0)
- goto out;
- isdn_lock_drivers();
- retval = 0;
- goto out;
- }
#ifdef CONFIG_ISDN_PPP
- if (minor <= ISDN_MINOR_PPPMAX) {
- retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
- if (retval == 0)
- isdn_lock_drivers();
- goto out;
- }
+ if (minor <= ISDN_MINOR_PPPMAX)
+ return isdn_ppp_open(ino, filep);
#endif
- out:
- return retval;
+
+ return -ENODEV;
}
static int
@@ -1698,42 +1772,21 @@
{
uint minor = minor(ino->i_rdev);
- lock_kernel();
- if (minor == ISDN_MINOR_STATUS) {
- infostruct *p = dev->infochain;
- infostruct *q = NULL;
-
- while (p) {
- if (p->private == (char *) &(filep->private_data)) {
- if (q)
- q->next = p->next;
- else
- dev->infochain = (infostruct *) (p->next);
- kfree(p);
- goto out;
- }
- q = p;
- p = (infostruct *) (p->next);
- }
- printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
- goto out;
- }
- isdn_unlock_drivers();
- if (minor <= ISDN_MINOR_BMAX)
- goto out;
- if (minor <= ISDN_MINOR_CTRLMAX) {
- if (dev->profd == current)
- dev->profd = NULL;
- goto out;
- }
+ if (minor == ISDN_MINOR_STATUS)
+ return isdn_status_release(ino, filep);
+
+ if (minor < ISDN_MINOR_CTRL)
+ return -ENODEV;
+
+ if (minor <= ISDN_MINOR_CTRLMAX)
+ return isdn_ctrl_release(ino, filep);
+
#ifdef CONFIG_ISDN_PPP
if (minor <= ISDN_MINOR_PPPMAX)
- isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
+ return isdn_ppp_release(ino, filep);
#endif
- out:
- unlock_kernel();
- return 0;
+ return -ENODEV;
}
static struct file_operations isdn_fops =
@@ -1875,32 +1928,6 @@
return;
}
restore_flags(flags);
-}
-
-/*
- * writebuf replacement for SKB_ABLE drivers
- */
-static int
-isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len,
- int user)
-{
- int ret;
- int hl = dev->drv[drvidx]->interface->hl_hdrlen;
- struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
-
- if (!skb)
- return 0;
- skb_reserve(skb, hl);
- if (user)
- copy_from_user(skb_put(skb, len), buf, len);
- else
- memcpy(skb_put(skb, len), buf, len);
- ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
- if (ret <= 0)
- dev_kfree_skb(skb);
- if (ret > 0)
- dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
- return ret;
}
/*
diff -u --recursive --new-file pre1/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- pre1/linux/drivers/isdn/isdn_common.h Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/isdn_common.h Thu Jan 17 14:04:15 2002
@@ -27,6 +27,8 @@
/* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void);
extern void isdn_MOD_DEC_USE_COUNT(void);
+extern void isdn_lock_drivers(void);
+extern void isdn_unlock_drivers(void);
extern void isdn_free_channel(int di, int ch, int usage);
extern void isdn_all_eaz(int di, int ch);
extern int isdn_command(isdn_ctrl *);
diff -u --recursive --new-file pre1/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- pre1/linux/drivers/isdn/isdn_ppp.c Thu Jan 3 12:20:10 2002
+++ linux/drivers/isdn/isdn_ppp.c Thu Jan 17 14:04:15 2002
@@ -11,6 +11,7 @@
#include
#include
+#include
#include
#include
@@ -269,21 +270,19 @@
*/
int
-isdn_ppp_open(int min, struct file *file)
+isdn_ppp_open(struct inode *ino, struct file *file)
{
+ uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
int slot;
struct ippp_struct *is;
- if (min < 0 || min > ISDN_MAX_CHANNELS)
- return -ENODEV;
-
slot = isdn_ppp_get_slot();
if (slot < 0) {
return -EBUSY;
}
is = file->private_data = ippp_table[slot];
- printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
+ printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, minor, is->state);
/* compression stuff */
is->link_compressor = is->compressor = NULL;
@@ -306,7 +305,7 @@
init_waitqueue_head(&is->wq);
is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
is->last = is->rq;
- is->minor = min;
+ is->minor = minor;
#ifdef CONFIG_ISDN_PPP_VJ
/*
* VJ header compression init
@@ -315,6 +314,7 @@
#endif
is->state = IPPP_OPEN;
+ isdn_lock_drivers();
return 0;
}
@@ -322,18 +322,19 @@
/*
* release ippp device
*/
-void
-isdn_ppp_release(int min, struct file *file)
+int
+isdn_ppp_release(struct inode *ino, struct file *file)
{
+ uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
int i;
struct ippp_struct *is;
- if (min < 0 || min >= ISDN_MAX_CHANNELS)
- return;
+ lock_kernel();
+
is = file->private_data;
if (is->debug & 0x1)
- printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
+ printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) is->lp);
if (is->lp) { /* a lp address says: this link is still up */
isdn_net_dev *p = is->lp->netdev;
@@ -381,6 +382,11 @@
/* this slot is ready for new connections */
is->state = 0;
+
+ isdn_unlock_drivers();
+
+ unlock_kernel();
+ return 0;
}
/*
@@ -413,7 +419,7 @@
* ippp device ioctl
*/
int
-isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
+isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long val;
int r,i,j;
@@ -425,7 +431,7 @@
lp = is->lp;
if (is->debug & 0x1)
- printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
+ printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", is->minor, cmd, is->state);
if (!(is->state & IPPP_OPEN))
return -EINVAL;
@@ -438,7 +444,7 @@
if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
- (int) min, (int) is->unit, (int) val);
+ (int) is->minor, (int) is->unit, (int) val);
return isdn_ppp_bundle(is, val);
#else
return -1;
@@ -582,6 +588,7 @@
unsigned long flags;
struct ippp_struct *is;
+ lock_kernel();
is = file->private_data;
if (is->debug & 0x2)
@@ -592,10 +599,13 @@
poll_wait(file, &is->wq, wait);
if (!(is->state & IPPP_OPEN)) {
- if(is->state == IPPP_CLOSEWAIT)
- return POLLHUP;
+ if(is->state == IPPP_CLOSEWAIT) {
+ mask = POLLHUP;
+ goto out;
+ }
printk(KERN_DEBUG "isdn_ppp: device not open\n");
- return POLLERR;
+ mask = POLLERR;
+ goto out;
}
/* we're always ready to send .. */
mask = POLLOUT | POLLWRNORM;
@@ -612,6 +622,9 @@
mask |= POLLIN | POLLRDNORM;
}
restore_flags(flags);
+
+ out:
+ unlock_kernel();
return mask;
}
@@ -678,21 +691,28 @@
*/
int
-isdn_ppp_read(int min, struct file *file, char *buf, int count)
+isdn_ppp_read(struct file *file, char *buf, int count, loff_t *off)
{
struct ippp_struct *is;
struct ippp_buf_queue *b;
- int r;
unsigned long flags;
unsigned char *save_buf;
+ int retval;
- is = file->private_data;
+ if (off != &file->f_pos)
+ return -ESPIPE;
+
+ lock_kernel();
- if (!(is->state & IPPP_OPEN))
- return 0;
+ is = file->private_data;
- if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
- return r;
+ if (!(is->state & IPPP_OPEN)) {
+ retval = 0;
+ goto out;
+ }
+ retval = verify_area(VERIFY_WRITE, (void *) buf, count);
+ if (retval)
+ goto out;
save_flags(flags);
cli();
@@ -701,7 +721,8 @@
save_buf = b->buf;
if (!save_buf) {
restore_flags(flags);
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto out;
}
if (b->len < count)
count = b->len;
@@ -713,7 +734,11 @@
copy_to_user(buf, save_buf, count);
kfree(save_buf);
- return count;
+ retval = count;
+
+ out:
+ unlock_kernel();
+ return retval;
}
/*
@@ -721,17 +746,25 @@
*/
int
-isdn_ppp_write(int min, struct file *file, const char *buf, int count)
+isdn_ppp_write(struct file *file, const char *buf, int count, loff_t *off)
{
isdn_net_local *lp;
struct ippp_struct *is;
int proto;
unsigned char protobuf[4];
+ int retval;
+
+ if (off != &file->f_pos)
+ return -ESPIPE;
+
+ lock_kernel();
is = file->private_data;
- if (!(is->state & IPPP_CONNECT))
- return 0;
+ if (!(is->state & IPPP_CONNECT)) {
+ retval = 0;
+ goto out;
+ }
lp = is->lp;
@@ -744,15 +777,18 @@
* Don't reset huptimer for
* LCP packets. (Echo requests).
*/
- if (copy_from_user(protobuf, buf, 4))
- return -EFAULT;
+ if (copy_from_user(protobuf, buf, 4)) {
+ retval = -EFAULT;
+ goto out;
+ }
proto = PPP_PROTOCOL(protobuf);
if (proto != PPP_LCP)
lp->huptimer = 0;
- if (lp->isdn_device < 0 || lp->isdn_channel < 0)
- return 0;
-
+ if (lp->isdn_device < 0 || lp->isdn_channel < 0) {
+ retval = 0;
+ goto out;
+ }
if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) {
@@ -767,13 +803,15 @@
skb = alloc_skb(hl+count, GFP_ATOMIC);
if (!skb) {
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
- return count;
+ retval = count;
+ goto out;
}
skb_reserve(skb, hl);
if (copy_from_user(skb_put(skb, count), buf, count))
{
kfree_skb(skb);
- return -EFAULT;
+ retval = -EFAULT;
+ goto out;
}
if (is->debug & 0x40) {
printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
@@ -785,7 +823,11 @@
isdn_net_write_super(lp, skb);
}
}
- return count;
+ retval = count;
+
+ out:
+ unlock_kernel();
+ return retval;
}
/*
diff -u --recursive --new-file pre1/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h
--- pre1/linux/drivers/isdn/isdn_ppp.h Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/isdn_ppp.h Thu Jan 17 14:04:15 2002
@@ -12,9 +12,13 @@
#include /* for PPP_PROTOCOL */
#include /* for isdn_ppp info */
-extern int isdn_ppp_read(int, struct file *, char *, int);
-extern int isdn_ppp_write(int, struct file *, const char *, int);
-extern int isdn_ppp_open(int, struct file *);
+extern int isdn_ppp_open(struct inode *, struct file *);
+extern int isdn_ppp_release(struct inode *, struct file *);
+extern int isdn_ppp_read(struct file *, char *, int, loff_t *off);
+extern int isdn_ppp_write(struct file *, const char *, int, loff_t *off);
+extern int isdn_ppp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *);
+
extern int isdn_ppp_init(void);
extern void isdn_ppp_cleanup(void);
extern int isdn_ppp_free(isdn_net_local *);
@@ -22,9 +26,6 @@
extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
-extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *);
-extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
-extern void isdn_ppp_release(int, struct file *);
extern int isdn_ppp_dial_slave(char *);
extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
diff -u --recursive --new-file pre1/linux/drivers/md/md.c linux/drivers/md/md.c
--- pre1/linux/drivers/md/md.c Thu Jan 10 10:15:38 2002
+++ linux/drivers/md/md.c Tue Jan 15 13:53:51 2002
@@ -3458,8 +3458,7 @@
* about not overloading the IO subsystem. (things like an
* e2fsck being done on the RAID array should execute fast)
*/
- if (current->need_resched)
- schedule();
+ cond_resched();
currspeed = (j-mddev->resync_mark_cnt)/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
diff -u --recursive --new-file pre1/linux/drivers/media/radio/radio-sf16fmi.c linux/drivers/media/radio/radio-sf16fmi.c
--- pre1/linux/drivers/media/radio/radio-sf16fmi.c Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/radio/radio-sf16fmi.c Tue Jan 15 13:53:51 2002
@@ -94,8 +94,7 @@
for(i=0; i< 100; i++)
{
udelay(1400);
- if(current->need_resched)
- schedule();
+ cond_resched();
}
/* If this becomes allowed use it ...
current->state = TASK_UNINTERRUPTIBLE;
@@ -121,8 +120,7 @@
for(i=0; i< 100; i++)
{
udelay(1400);
- if(current->need_resched)
- schedule();
+ cond_resched();
}
/* If this becomes allowed use it ...
current->state = TASK_UNINTERRUPTIBLE;
diff -u --recursive --new-file pre1/linux/drivers/media/video/c-qcam.c linux/drivers/media/video/c-qcam.c
--- pre1/linux/drivers/media/video/c-qcam.c Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/c-qcam.c Tue Jan 15 13:53:51 2002
@@ -425,8 +425,7 @@
wantlen -= t;
if (t < s)
break;
- if (current->need_resched)
- schedule();
+ cond_resched();
}
len = outptr;
@@ -445,8 +444,7 @@
int l;
do {
l = qcam_read_bytes(q, tmpbuf, 3);
- if (current->need_resched)
- schedule();
+ cond_resched();
} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
if (force_rgb) {
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
@@ -478,8 +476,7 @@
int l;
do {
l = qcam_read_bytes(q, tmpbuf, 1);
- if (current->need_resched)
- schedule();
+ cond_resched();
} while (l && tmpbuf[0] == 0x7e);
l = qcam_read_bytes(q, tmpbuf+1, 2);
if (force_rgb) {
diff -u --recursive --new-file pre1/linux/drivers/media/video/cpia.c linux/drivers/media/video/cpia.c
--- pre1/linux/drivers/media/video/cpia.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/media/video/cpia.c Tue Jan 15 13:53:51 2002
@@ -2147,8 +2147,7 @@
/* loop until image ready */
do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
while (cam->params.status.streamState != STREAM_READY) {
- if (current->need_resched)
- schedule();
+ cond_resched();
current->state = TASK_INTERRUPTIBLE;
@@ -2163,8 +2162,7 @@
}
/* grab image from camera */
- if (current->need_resched)
- schedule();
+ cond_resched();
oldjif = jiffies;
image_size = cam->ops->streamRead(cam->lowlevel_data,
@@ -2189,8 +2187,7 @@
/* decompress and convert image to by copying it from
* raw_image to decompressed_frame
*/
- if (current->need_resched)
- schedule();
+ cond_resched();
cam->image_size = parse_picture(cam, image_size);
if (cam->image_size <= 0)
diff -u --recursive --new-file pre1/linux/drivers/media/video/cpia_pp.c linux/drivers/media/video/cpia_pp.c
--- pre1/linux/drivers/media/video/cpia_pp.c Thu Oct 25 13:53:47 2001
+++ linux/drivers/media/video/cpia_pp.c Tue Jan 15 13:53:51 2002
@@ -392,7 +392,7 @@
endseen = 0;
block_size = PARPORT_CHUNK_SIZE;
while( !cam->image_complete ) {
- if(current->need_resched) schedule();
+ cond_resched();
new_bytes = cpia_pp_read(cam->port, buffer, block_size );
if( new_bytes <= 0 ) {
diff -u --recursive --new-file pre1/linux/drivers/media/video/saa5249.c linux/drivers/media/video/saa5249.c
--- pre1/linux/drivers/media/video/saa5249.c Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/saa5249.c Tue Jan 15 13:53:51 2002
@@ -127,11 +127,7 @@
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
-#define RESCHED \
- do { \
- if (current->need_resched) \
- schedule(); \
- } while (0)
+#define RESCHED do { cond_resched(); } while(0)
static struct video_device saa_template; /* Declared near bottom */
diff -u --recursive --new-file pre1/linux/drivers/mtd/chips/amd_flash.c linux/drivers/mtd/chips/amd_flash.c
--- pre1/linux/drivers/mtd/chips/amd_flash.c Thu Oct 4 15:14:59 2001
+++ linux/drivers/mtd/chips/amd_flash.c Tue Jan 15 13:53:51 2002
@@ -889,7 +889,7 @@
times_left = 500000;
while (times_left-- && flash_is_busy(map, adr, private->interleave)) {
- if (current->need_resched) {
+ if (need_resched()) {
spin_unlock_bh(chip->mutex);
schedule();
spin_lock_bh(chip->mutex);
@@ -1126,7 +1126,7 @@
/* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex);
- if (current->need_resched)
+ if (need_resched())
schedule();
else
udelay(1);
diff -u --recursive --new-file pre1/linux/drivers/mtd/devices/doc2000.c linux/drivers/mtd/devices/doc2000.c
--- pre1/linux/drivers/mtd/devices/doc2000.c Thu Oct 4 15:14:59 2001
+++ linux/drivers/mtd/devices/doc2000.c Tue Jan 15 13:53:51 2002
@@ -97,7 +97,7 @@
DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
return -EIO;
}
- if (current->need_resched) {
+ if (need_resched()) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
diff -u --recursive --new-file pre1/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- pre1/linux/drivers/net/acenic.h Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/acenic.h Tue Jan 15 14:34:38 2002
@@ -585,7 +585,7 @@
struct ring_info {
struct sk_buff *skb;
- dma_addr_t mapping;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
};
@@ -596,8 +596,8 @@
*/
struct tx_ring_info {
struct sk_buff *skb;
- dma_addr_t mapping;
- int maplen;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+ DECLARE_PCI_UNMAP_LEN(maplen)
};
diff -u --recursive --new-file pre1/linux/drivers/net/pcmcia/wavelan.h linux/drivers/net/pcmcia/wavelan.h
--- pre1/linux/drivers/net/pcmcia/wavelan.h Fri Mar 2 11:02:15 2001
+++ linux/drivers/net/pcmcia/wavelan.h Tue Jan 15 18:54:35 2002
@@ -88,6 +88,7 @@
*/
const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
+
/*************************** PC INTERFACE ****************************/
/* WaveLAN host interface definitions */
@@ -316,6 +317,7 @@
/* Calculate offset of a field in the above structure */
#define mmwoff(p,f) (unsigned short)((void *)(&((mmw_t *)((void *)0 + (p)))->f) - (void *)0)
+
/*
* Modem Management Controller (MMC) read structure.
*/
@@ -372,6 +374,7 @@
/* Calculate offset of a field in the above structure */
#define mmroff(p,f) (unsigned short)((void *)(&((mmr_t *)((void *)0 + (p)))->f) - (void *)0)
+
/* Make the two above structures one */
typedef union mm_t
diff -u --recursive --new-file pre1/linux/drivers/net/pcmcia/wavelan_cs.c linux/drivers/net/pcmcia/wavelan_cs.c
--- pre1/linux/drivers/net/pcmcia/wavelan_cs.c Fri Nov 9 15:22:54 2001
+++ linux/drivers/net/pcmcia/wavelan_cs.c Tue Jan 15 18:54:35 2002
@@ -22,7 +22,7 @@
#ifdef WAVELAN_ROAMING
* Roaming support added 07/22/98 by Justin Seger (jseger@media.mit.edu)
* based on patch by Joe Finney from Lancaster University.
-#endif :-)
+#endif
*
* Lucent (formerly AT&T GIS, formerly NCR) WaveLAN PCMCIA card: An
* Ethernet-like radio transceiver controlled by an Intel 82593 coprocessor.
@@ -37,12 +37,6 @@
* Apr 2 '98 made changes to bring the i82593 control/int handling in line
* with offical specs...
*
- * Changes:
- * Arnaldo Carvalho de Melo - 08/08/2000
- * - reorganize kmallocs in wavelan_attach, checking all for failure
- * and releasing the previous allocations if one fails
- *
- *
****************************************************************************
* Copyright 1995
* Anthony D. Joseph
@@ -72,6 +66,34 @@
/*------------------------------------------------------------------*/
/*
+ * Wrapper for disabling interrupts.
+ * (note : inline, so optimised away)
+ */
+static inline void
+wv_splhi(net_local * lp,
+ unsigned long * pflags)
+{
+ spin_lock_irqsave(&lp->spinlock, *pflags);
+ /* Note : above does the cli(); itself */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper for re-enabling interrupts.
+ */
+static inline void
+wv_splx(net_local * lp,
+ unsigned long * pflags)
+{
+ spin_unlock_irqrestore(&lp->spinlock, *pflags);
+
+ /* Note : enabling interrupts on the hardware is done in wv_ru_start()
+ * via : outb(OP1_INT_ENABLE, LCCR(base));
+ */
+}
+
+/*------------------------------------------------------------------*/
+/*
* Wrapper for reporting error to cardservices
*/
static void cs_error(client_handle_t handle, int func, int ret)
@@ -103,7 +125,7 @@
/******************* MODEM MANAGEMENT SUBROUTINES *******************/
/*
- * Usefull subroutines to manage the modem of the wavelan
+ * Useful subroutines to manage the modem of the wavelan
*/
/*------------------------------------------------------------------*/
@@ -138,7 +160,7 @@
{
hacr_write(base, hacr);
/* delay might only be needed sometimes */
- mdelay(1L);
+ mdelay(1);
} /* hacr_write_slow */
/*------------------------------------------------------------------*/
@@ -529,7 +551,7 @@
lp->curr_point=NULL; /* No default WavePoint */
lp->cell_search=0;
- lp->cell_timer.data=(int)lp; /* Start cell expiry timer */
+ lp->cell_timer.data=(long)lp; /* Start cell expiry timer */
lp->cell_timer.function=wl_cell_expiry;
lp->cell_timer.expires=jiffies+CELL_TIMEOUT;
add_timer(&lp->cell_timer);
@@ -569,18 +591,18 @@
#endif
/* Disable interrupts & save flags */
- spin_lock_irqsave (&lp->lock, flags);
+ wv_splhi(lp, &flags);
m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00;
mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1);
- /* ReEnable interrupts & restore flags */
- spin_unlock_irqrestore (&lp->lock, flags);
-
if(mode==NWID_PROMISC)
lp->cell_search=1;
else
- lp->cell_search=0;
+ lp->cell_search=0;
+
+ /* ReEnable interrupts & restore flags */
+ wv_splx(lp, &flags);
}
/* Find a record in the WavePoint table matching a given NWID */
@@ -737,7 +759,7 @@
ioaddr_t base = lp->dev->base_addr;
mm_t m;
unsigned long flags;
-
+
if(wavepoint==lp->curr_point) /* Sanity check... */
{
wv_nwid_filter(!NWID_PROMISC,lp);
@@ -749,16 +771,16 @@
#endif
/* Disable interrupts & save flags */
- spin_lock_irqsave(&lp->lock, flags);
-
+ wv_splhi(lp, &flags);
+
m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF;
m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8;
mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2);
/* ReEnable interrupts & restore flags */
- spin_unlock_irqrestore (&lp->lock, flags);
-
+ wv_splx(lp, &flags);
+
wv_nwid_filter(!NWID_PROMISC,lp);
lp->curr_point=wavepoint;
}
@@ -775,6 +797,11 @@
wavepoint_history *wavepoint=NULL; /* WavePoint table entry */
net_local *lp=(net_local *)dev->priv; /* Device info */
+#if 0
+ /* Some people don't need this, some other may need it */
+ nwid=nwid^ntohs(beacon->domain_id);
+#endif
+
#if WAVELAN_ROAMING_DEBUG > 1
printk(KERN_DEBUG "WaveLAN: beacon, dev %s:\n",dev->name);
printk(KERN_DEBUG "Domain: %.4X NWID: %.4X SigQual=%d\n",ntohs(beacon->domain_id),nwid,sigqual);
@@ -832,7 +859,9 @@
/*------------------------------------------------------------------*/
/*
* Routine to synchronously send a command to the i82593 chip.
- * Should be called with interrupts enabled.
+ * Should be called with interrupts disabled.
+ * (called by wv_packet_write(), wv_ru_stop(), wv_ru_start(),
+ * wv_82593_config() & wv_diag())
*/
static int
wv_82593_cmd(device * dev,
@@ -841,74 +870,98 @@
int result)
{
ioaddr_t base = dev->base_addr;
- net_local * lp = (net_local *)dev->priv;
int status;
+ int wait_completed;
long spin;
- u_long flags;
/* Spin until the chip finishes executing its current command (if any) */
+ spin = 1000;
do
{
- spin_lock_irqsave (&lp->lock, flags);
+ /* Time calibration of the loop */
+ udelay(10);
+
+ /* Read the interrupt register */
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- spin_unlock_irqrestore (&lp->lock, flags);
}
- while((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE);
+ while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0));
- /* We are waiting for command completion */
- wv_wait_completed = TRUE;
+ /* If the interrupt hasn't be posted */
+ if(spin <= 0)
+ {
+#ifdef DEBUG_INTERRUPT_ERROR
+ printk(KERN_INFO "wv_82593_cmd: %s timeout (previous command), status 0x%02x\n",
+ str, status);
+#endif
+ return(FALSE);
+ }
/* Issue the command to the controller */
outb(cmd, LCCR(base));
- /* If we don't have to check the result of the command */
+ /* If we don't have to check the result of the command
+ * Note : this mean that the irq handler will deal with that */
if(result == SR0_NO_RESULT)
- {
- wv_wait_completed = FALSE;
- return(TRUE);
- }
+ return(TRUE);
- /* Busy wait while the LAN controller executes the command.
- * Note : wv_wait_completed should be volatile */
- spin = 0;
- while(wv_wait_completed && (spin++ < 1000))
- udelay(10);
+ /* We are waiting for command completion */
+ wait_completed = TRUE;
- /* If the interrupt handler hasn't be called */
- if(wv_wait_completed)
+ /* Busy wait while the LAN controller executes the command. */
+ spin = 1000;
+ do
{
- outb(OP0_NOP, LCCR(base));
+ /* Time calibration of the loop */
+ udelay(10);
+
+ /* Read the interrupt register */
+ outb(CR0_STATUS_0 | OP0_NOP, LCCR(base));
status = inb(LCSR(base));
- if(status & SR0_INTERRUPT)
+
+ /* Check if there was an interrupt posted */
+ if((status & SR0_INTERRUPT))
{
- /* There was an interrupt : call the interrupt handler */
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_WARNING "wv_82593_cmd: interrupt handler not installed or interrupt disabled\n");
-#endif
+ /* Acknowledge the interrupt */
+ outb(CR0_INT_ACK | OP0_NOP, LCCR(base));
- wavelan_interrupt(dev->irq, (void *) dev,
- (struct pt_regs *) NULL);
+ /* Check if interrupt is a command completion */
+ if(((status & SR0_BOTH_RX_TX) != SR0_BOTH_RX_TX) &&
+ ((status & SR0_BOTH_RX_TX) != 0x0) &&
+ !(status & SR0_RECEPTION))
+ {
+ /* Signal command completion */
+ wait_completed = FALSE;
+ }
+ else
+ {
+ /* Note : Rx interrupts will be handled later, because we can
+ * handle multiple Rx packets at once */
+#ifdef DEBUG_INTERRUPT_INFO
+ printk(KERN_INFO "wv_82593_cmd: not our interrupt\n");
+#endif
+ }
}
- else
- {
- wv_wait_completed = 0; /* XXX */
+ }
+ while(wait_completed && (spin-- > 0));
+
+ /* If the interrupt hasn't be posted */
+ if(wait_completed)
+ {
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "wv_82593_cmd: %s timeout, status0 0x%02x\n",
- str, status);
+ printk(KERN_INFO "wv_82593_cmd: %s timeout, status 0x%02x\n",
+ str, status);
#endif
- /* We probably should reset the controller here */
- return(FALSE);
- }
+ return(FALSE);
}
- /* Check the return code provided by the interrupt handler against
+ /* Check the return code returned by the card (see above) against
* the expected return code provided by the caller */
- if((lp->status & SR0_EVENT_MASK) != result)
+ if((status & SR0_EVENT_MASK) != result)
{
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "wv_82593_cmd: %s failed, status0 = 0x%x\n",
- str, lp->status);
+ printk(KERN_INFO "wv_82593_cmd: %s failed, status = 0x%x\n",
+ str, status);
#endif
return(FALSE);
}
@@ -924,14 +977,16 @@
static inline int
wv_diag(device * dev)
{
+ int ret = FALSE;
+
if(wv_82593_cmd(dev, "wv_diag(): diagnose",
OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED))
- return(TRUE);
+ ret = TRUE;
#ifdef DEBUG_CONFIG_ERROR
printk(KERN_INFO "wavelan_cs: i82593 Self Test failed!\n");
#endif
- return(FALSE);
+ return(ret);
} /* wv_diag */
/*------------------------------------------------------------------*/
@@ -951,15 +1006,6 @@
int chunk_len;
char * buf_ptr = buf;
-#ifdef OLDIES
- /* After having check skb_put (net/core/skbuff.c) in the kernel, it seem
- * quite safe to remove this... */
-
- /* If buf is NULL, just increment the ring buffer pointer */
- if(buf == NULL)
- return((ring_ptr - RX_BASE + len) % RX_SIZE + RX_BASE);
-#endif
-
/* Get all the buffer */
while(len > 0)
{
@@ -990,70 +1036,32 @@
* wavelan_interrupt is not an option...), so you may experience
* some delay sometime...
*/
-static inline void wv_82593_reconfig (device * dev)
+static inline void
+wv_82593_reconfig(device * dev)
{
- net_local *lp = (net_local *) dev->priv;
- dev_link_t *link = ((net_local *) dev->priv)->link;
+ net_local * lp = (net_local *)dev->priv;
+ dev_link_t * link = ((net_local *) dev->priv)->link;
+ unsigned long flags;
+
+ /* Arm the flag, will be cleard in wv_82593_config() */
+ lp->reconfig_82593 = TRUE;
- /* Check if we can do it now ! */
- if (!(link->open)) {
- lp->reconfig_82593 = TRUE;
+ /* Check if we can do it now ! */
+ if((link->open) && (netif_running(dev)) && !(netif_queue_stopped(dev)))
+ {
+ wv_splhi(lp, &flags); /* Disable interrupts */
+ wv_82593_config(dev);
+ wv_splx(lp, &flags); /* Re-enable interrupts */
+ }
+ else
+ {
#ifdef DEBUG_IOCTL_INFO
- printk (KERN_DEBUG "%s: wv_82593_reconfig(): delayed (link = %d)\n",
- dev->name, link->open);
+ printk(KERN_DEBUG
+ "%s: wv_82593_reconfig(): delayed (state = %lX, link = %d)\n",
+ dev->name, dev->state, link->open);
#endif
- } else {
- netif_stop_queue (dev);
-
- lp->reconfig_82593 = FALSE;
- wv_82593_config (dev);
- netif_wake_queue (dev);
- }
-}
-
-#ifdef OLDIES
-/*------------------------------------------------------------------*/
-/*
- * Dumps the current i82593 receive buffer to the console.
- */
-static void wavelan_dump(device *dev)
-{
- ioaddr_t base = dev->base_addr;
- int i, c;
-
- /* disable receiver so we can use channel 1 */
- outb(OP0_RCV_DISABLE, LCCR(base));
-
- /* reset receive DMA pointer */
- hacr_write_slow(base, HACR_PWR_STAT | HACR_RX_DMA_RESET);
- hacr_write(base, HACR_DEFAULT);
-
- /* dump into receive buffer */
- wv_82593_cmd(dev, "wavelan_dump(): dump", CR0_CHNL|OP0_DUMP, SR0_DUMP_DONE);
-
- /* set read pointer to start of receive buffer */
- outb(0, PIORL(base));
- outb(0, PIORH(base));
-
- printk(KERN_DEBUG "wavelan_cs: dump:\n");
- printk(KERN_DEBUG " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
- for(i = 0; i < 73; i++){
- if((i % 16) == 0) {
- printk("\n0x%02x:", i);
- if (!i) {
- printk(" ");
- continue;
- }
}
- c = inb(PIOP(base));
- printk("%02x ", c);
- }
- printk("\n");
-
- /* enable the receiver again */
- wv_ru_start(dev);
}
-#endif
/********************* DEBUG & INFO SUBROUTINES *********************/
/*
@@ -1171,6 +1179,8 @@
return;
}
+ wv_splhi(lp, &flags);
+
/* Read the mmc */
mmc_out(base, mmwoff(0, mmw_freeze), 1);
mmc_read(base, 0, (u_char *)&m, sizeof(m));
@@ -1181,6 +1191,8 @@
lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
#endif /* WIRELESS_EXT */
+ wv_splx(lp, &flags);
+
printk(KERN_DEBUG "##### wavelan modem status registers: #####\n");
#ifdef DEBUG_SHOW_UNUSED
printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1265,6 +1277,7 @@
wv_dev_show(device * dev)
{
printk(KERN_DEBUG "dev:");
+ printk(" state=%lX,", dev->state);
printk(" trans_start=%ld,", dev->trans_start);
printk(" flags=0x%x,", dev->flags);
printk("\n");
@@ -1404,7 +1417,7 @@
printk("2430.5");
break;
default:
- printk("unknown");
+ printk("???");
}
}
@@ -1719,7 +1732,7 @@
memcmp(dac, dac_verify, 2 * 2))
{
#ifdef DEBUG_IOCTL_ERROR
- printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (?)\n");
+ printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (??)\n");
#endif
return -EOPNOTSUPP;
}
@@ -1892,7 +1905,7 @@
#endif
/* Disable interrupts & save flags */
- spin_lock_irqsave (&lp->lock, flags);
+ wv_splhi(lp, &flags);
/* Look what is the request */
switch(cmd)
@@ -1968,7 +1981,7 @@
case SIOCGIWFREQ:
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
- * (does it work for everybody XXX - especially old cards...) */
+ * (does it work for everybody ??? - especially old cards...) */
if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
(MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
{
@@ -2239,15 +2252,17 @@
{
struct iw_range range;
- /* Set the length (very important for backward compatibility) */
- wrq->u.data.length = sizeof(struct iw_range);
+ /* Set the length (very important for backward compatibility) */
+ wrq->u.data.length = sizeof(struct iw_range);
- /* Set all the info we don't care or don't know about to zero */
- memset(&range, 0, sizeof(range));
+ /* Set all the info we don't care or don't know about to zero */
+ memset(&range, 0, sizeof(range));
- /* Set the Wireless Extension versions */
- range.we_version_compiled = WIRELESS_EXT;
- range.we_version_source = 9; /* Nothing for us in v10 and v11 */
+#if WIRELESS_EXT > 10
+ /* Set the Wireless Extension versions */
+ range.we_version_compiled = WIRELESS_EXT;
+ range.we_version_source = 9; /* Nothing for us in v10 and v11 */
+#endif /* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range.throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */
@@ -2517,7 +2532,7 @@
}
/* ReEnable interrupts & restore flags */
- spin_unlock_irqrestore (&lp->lock, flags);
+ wv_splx(lp, &flags);
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
@@ -2543,11 +2558,8 @@
printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
#endif
- if (lp == NULL) /* XXX will this ever occur? */
- return NULL;
-
/* Disable interrupts & save flags */
- spin_lock_irqsave (&lp->lock, flags);
+ wv_splhi(lp, &flags);
wstats = &lp->wstats;
@@ -2573,7 +2585,7 @@
wstats->discard.misc = 0L;
/* ReEnable interrupts & restore flags */
- spin_unlock_irqrestore (&lp->lock, flags);
+ wv_splx(lp, &flags);
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
@@ -2692,12 +2704,6 @@
skb->protocol = eth_type_trans(skb, dev);
#ifdef DEBUG_RX_INFO
- /* Another glitch : Due to the way the GET_PACKET macro is written,
- * we are not sure to have the same thing in skb->data. On the other
- * hand, skb->mac.raw is not defined everywhere...
- * For versions between 1.2.13 and those where skb->mac.raw appear,
- * I don't have a clue...
- */
wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
#endif /* DEBUG_RX_INFO */
@@ -2731,9 +2737,7 @@
wl_roam_gather(dev, skb->data, stats);
#endif /* WAVELAN_ROAMING */
- /* Spying stuff */
#ifdef WIRELESS_SPY
- /* Same as above */
wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats);
#endif /* WIRELESS_SPY */
#ifdef HISTOGRAM
@@ -2766,6 +2770,7 @@
* called to do the actual transfer of the card's data including the
* ethernet header into a packet consisting of an sk_buff chain.
* (called by wavelan_interrupt())
+ * Note : the spinlock is already grabbed for us and irq are disabled.
*/
static inline void
wv_packet_rcv(device * dev)
@@ -2916,7 +2921,7 @@
printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
#endif
- spin_lock_irqsave (&lp->lock, flags);
+ wv_splhi(lp, &flags);
/* Check if we need some padding */
if(clen < ETH_ZLEN)
@@ -2946,15 +2951,7 @@
/* Keep stats up to date */
lp->stats.tx_bytes += length;
- /* If watchdog not already active, activate it... */
- if (!timer_pending(&lp->watchdog))
- {
- /* set timer to expire in WATCHDOG_JIFFIES */
- lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&lp->watchdog);
- }
-
- spin_unlock_irqrestore (&lp->lock, flags);
+ wv_splx(lp, &flags);
#ifdef DEBUG_TX_INFO
wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
@@ -2963,56 +2960,57 @@
#ifdef DEBUG_TX_TRACE
printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
#endif
-
- netif_start_queue (dev);
}
/*------------------------------------------------------------------*/
/*
* This routine is called when we want to send a packet (NET3 callback)
- * In this routine, we check if the hardware is ready to accept
+ * In this routine, we check if the harware is ready to accept
* the packet. We also prevent reentrance. Then, we call the function
* to send the packet...
*/
-static int wavelan_packet_xmit (struct sk_buff *skb,
- device * dev)
+static int
+wavelan_packet_xmit(struct sk_buff * skb,
+ device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local * lp = (net_local *)dev->priv;
+ unsigned long flags;
#ifdef DEBUG_TX_TRACE
- printk (KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
- (unsigned) skb);
+ printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
+ (unsigned) skb);
#endif
- /*
- * For ethernet, fill in the header.
- */
+ /*
+ * Block a timer-based transmit from overlapping a previous transmit.
+ * In other words, prevent reentering this routine.
+ */
+ netif_stop_queue(dev);
- netif_stop_queue (dev);
+ /* If somebody has asked to reconfigure the controller,
+ * we can do it now */
+ if(lp->reconfig_82593)
+ {
+ wv_splhi(lp, &flags); /* Disable interrupts */
+ wv_82593_config(dev);
+ wv_splx(lp, &flags); /* Re-enable interrupts */
+ /* Note : the configure procedure was totally synchronous,
+ * so the Tx buffer is now free */
+ }
- /*
- * Block a timer-based transmit from overlapping a previous transmit.
- * In other words, prevent reentering this routine.
- */
- if (1) {
- /* If somebody has asked to reconfigure the controller, we can do it now */
- if (lp->reconfig_82593) {
- lp->reconfig_82593 = FALSE;
- wv_82593_config (dev);
- }
#ifdef DEBUG_TX_ERROR
- if (skb->next)
- printk (KERN_INFO "skb has next\n");
+ if (skb->next)
+ printk(KERN_INFO "skb has next\n");
#endif
- wv_packet_write (dev, skb->data, skb->len);
- }
- dev_kfree_skb (skb);
+ wv_packet_write(dev, skb->data, skb->len);
+
+ dev_kfree_skb(skb);
#ifdef DEBUG_TX_TRACE
- printk (KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return (0);
+ return(0);
}
/********************** HARDWARE CONFIGURATION **********************/
@@ -3165,7 +3163,7 @@
*/
/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
- * (does it work for everybody XXX - especially old cards...) */
+ * (does it work for everybody ??? - especially old cards...) */
/* Note : WFREQSEL verify that it is able to read from EEprom
* a sensible frequency (address 0x00) + that MMR_FEE_STATUS_ID
* is 0xA (Xilinx version) or 0xB (Ariadne version).
@@ -3223,7 +3221,7 @@
wv_ru_stop(device * dev)
{
ioaddr_t base = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local * lp = (net_local *) dev->priv;
unsigned long flags;
int status;
int spin;
@@ -3232,35 +3230,35 @@
printk(KERN_DEBUG "%s: ->wv_ru_stop()\n", dev->name);
#endif
+ wv_splhi(lp, &flags);
+
/* First, send the LAN controller a stop receive command */
wv_82593_cmd(dev, "wv_graceful_shutdown(): stop-rcv",
OP0_STOP_RCV, SR0_NO_RESULT);
/* Then, spin until the receive unit goes idle */
- spin = 0;
+ spin = 300;
do
{
udelay(10);
- spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- spin_unlock_irqrestore (&lp->lock, flags);
}
- while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin++ < 300));
+ while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin-- > 0));
/* Now, spin until the chip finishes executing its current command */
do
{
udelay(10);
- spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- spin_unlock_irqrestore (&lp->lock, flags);
}
- while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin++ < 300));
+ while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0));
+
+ wv_splx(lp, &flags);
/* If there was a problem */
- if(spin > 300)
+ if(spin <= 0)
{
#ifdef DEBUG_CONFIG_ERROR
printk(KERN_INFO "%s: wv_ru_stop(): The chip doesn't want to stop...\n",
@@ -3287,6 +3285,7 @@
{
ioaddr_t base = dev->base_addr;
net_local * lp = (net_local *) dev->priv;
+ unsigned long flags;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
@@ -3300,6 +3299,8 @@
if(!wv_ru_stop(dev))
return FALSE;
+ wv_splhi(lp, &flags);
+
/* Now we know that no command is being executed. */
/* Set the receive frame pointer and stop pointer */
@@ -3309,8 +3310,17 @@
/* Reset ring management. This sets the receive frame pointer to 1 */
outb(OP1_RESET_RING_MNGMT, LCCR(base));
+#if 0
+ /* XXX the i82593 manual page 6-4 seems to indicate that the stop register
+ should be set as below */
+ /* outb(CR1_STOP_REG_UPDATE|((RX_SIZE - 0x40)>> RX_SIZE_SHIFT),LCCR(base));*/
+#elif 0
+ /* but I set it 0 instead */
+ lp->stop = 0;
+#else
/* but I set it to 3 bytes per packet less than 8K */
lp->stop = (0 + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE;
+#endif
outb(CR1_STOP_REG_UPDATE | (lp->stop >> RX_SIZE_SHIFT), LCCR(base));
outb(OP1_INT_ENABLE, LCCR(base));
outb(OP1_SWIT_TO_PORT_0, LCCR(base));
@@ -3326,17 +3336,15 @@
#ifdef DEBUG_I82593_SHOW
{
int status;
- unsigned long flags;
- int i = 0;
+ int opri;
+ int spin = 10000;
/* spin until the chip starts receiving */
do
{
- spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- spin_unlock_irqrestore (&lp->lock, flags);
- if(i++ > 10000)
+ if(spin-- <= 0)
break;
}
while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_ACTIVE) &&
@@ -3345,6 +3353,9 @@
(status & SR3_RCV_STATE_MASK), i);
}
#endif
+
+ wv_splx(lp, &flags);
+
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
#endif
@@ -3363,6 +3374,7 @@
ioaddr_t base = dev->base_addr;
net_local * lp = (net_local *) dev->priv;
struct i82593_conf_block cfblk;
+ int ret = TRUE;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_82593_config()\n", dev->name);
@@ -3457,7 +3469,7 @@
hacr_write(base, HACR_DEFAULT);
if(!wv_82593_cmd(dev, "wv_82593_config(): configure",
OP0_CONFIGURE, SR0_CONFIGURE_DONE))
- return(FALSE);
+ ret = FALSE;
/* Initialize adapter's ethernet MAC address */
outb(TX_BASE & 0xff, PIORL(base));
@@ -3471,7 +3483,7 @@
hacr_write(base, HACR_DEFAULT);
if(!wv_82593_cmd(dev, "wv_82593_config(): ia-setup",
OP0_IA_SETUP, SR0_IA_SETUP_DONE))
- return(FALSE);
+ ret = FALSE;
#ifdef WAVELAN_ROAMING
/* If roaming is enabled, join the "Beacon Request" multicast group... */
@@ -3508,14 +3520,17 @@
hacr_write(base, HACR_DEFAULT);
if(!wv_82593_cmd(dev, "wv_82593_config(): mc-setup",
OP0_MC_SETUP, SR0_MC_SETUP_DONE))
- return(FALSE);
+ ret = FALSE;
lp->mc_count = dev->mc_count; /* remember to avoid repeated reset */
}
+ /* Job done, clear the flag */
+ lp->reconfig_82593 = FALSE;
+
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: <-wv_82593_config()\n", dev->name);
#endif
- return(TRUE);
+ return(ret);
}
/*------------------------------------------------------------------*/
@@ -3594,6 +3609,8 @@
{
net_local * lp = (net_local *) dev->priv;
ioaddr_t base = dev->base_addr;
+ unsigned long flags;
+ int ret = FALSE;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_hw_config()\n", dev->name);
@@ -3612,50 +3629,78 @@
if(wv_pcmcia_reset(dev) == FALSE)
return FALSE;
- /* Power UP the module + reset the modem + reset host adapter
- * (in fact, reset DMA channels) */
- hacr_write_slow(base, HACR_RESET);
- hacr_write(base, HACR_DEFAULT);
+ /* Disable interrupts */
+ wv_splhi(lp, &flags);
- /* Check if the module has been powered up... */
- if(hasr_read(base) & HASR_NO_CLK)
+ /* Disguised goto ;-) */
+ do
{
+ /* Power UP the module + reset the modem + reset host adapter
+ * (in fact, reset DMA channels) */
+ hacr_write_slow(base, HACR_RESET);
+ hacr_write(base, HACR_DEFAULT);
+
+ /* Check if the module has been powered up... */
+ if(hasr_read(base) & HASR_NO_CLK)
+ {
#ifdef DEBUG_CONFIG_ERRORS
- printk(KERN_WARNING "%s: wv_hw_config(): modem not connected or not a wavelan card\n",
- dev->name);
+ printk(KERN_WARNING "%s: wv_hw_config(): modem not connected or not a wavelan card\n",
+ dev->name);
#endif
- return FALSE;
- }
+ break;
+ }
- /* initialize the modem */
- if(wv_mmc_init(dev) == FALSE)
- return FALSE;
+ /* initialize the modem */
+ if(wv_mmc_init(dev) == FALSE)
+ {
+#ifdef DEBUG_CONFIG_ERRORS
+ printk(KERN_WARNING "%s: wv_hw_config(): Can't configure the modem\n",
+ dev->name);
+#endif
+ break;
+ }
- /* reset the LAN controller (i82593) */
- outb(OP0_RESET, LCCR(base));
- mdelay(1); /* A bit crude ! */
-
- /* Initialize the LAN controller */
- if((wv_82593_config(dev) == FALSE) ||
- (wv_diag(dev) == FALSE))
- {
+ /* reset the LAN controller (i82593) */
+ outb(OP0_RESET, LCCR(base));
+ mdelay(1); /* A bit crude ! */
+
+ /* Initialize the LAN controller */
+ if(wv_82593_config(dev) == FALSE)
+ {
#ifdef DEBUG_CONFIG_ERRORS
- printk(KERN_INFO "%s: wv_hw_config(): i82593 init failed\n", dev->name);
+ printk(KERN_INFO "%s: wv_hw_config(): i82593 init failed\n",
+ dev->name);
#endif
- return FALSE;
- }
+ break;
+ }
- /*
- * insert code for loopback test here
- */
+ /* Diagnostic */
+ if(wv_diag(dev) == FALSE)
+ {
+#ifdef DEBUG_CONFIG_ERRORS
+ printk(KERN_INFO "%s: wv_hw_config(): i82593 diagnostic failed\n",
+ dev->name);
+#endif
+ break;
+ }
- /* The device is now configured */
- lp->configured = 1;
+ /*
+ * insert code for loopback test here
+ */
+
+ /* The device is now configured */
+ lp->configured = 1;
+ ret = TRUE;
+ }
+ while(0);
+
+ /* Re-enable interrupts */
+ wv_splx(lp, &flags);
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: <-wv_hw_config()\n", dev->name);
#endif
- return TRUE;
+ return(ret);
}
/*------------------------------------------------------------------*/
@@ -3675,10 +3720,6 @@
printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name);
#endif
- /* If watchdog was activated, kill it ! */
- if (timer_pending(&lp->watchdog))
- del_timer(&lp->watchdog);
-
lp->nresets++;
lp->configured = 0;
@@ -3786,13 +3827,13 @@
}
/*
- * Allocate a 4K memory window. Note that the dev_link_t
+ * Allocate a small memory window. Note that the dev_link_t
* structure provides space for one window handle -- if your
* device needs several windows, you'll need to keep track of
* the handles in your private data structure, link->priv.
*/
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0; req.Size = 0x1000;
+ req.Base = req.Size = 0;
req.AccessSpeed = mem_speed;
link->win = (window_handle_t)link->handle;
i = CardServices(RequestWindow, &link->win, &req);
@@ -3803,7 +3844,7 @@
}
dev->rmem_start = dev->mem_start =
- (u_long)ioremap(req.Base, 0x1000);
+ (u_long)ioremap(req.Base, req.Size);
dev->rmem_end = dev->mem_end = dev->mem_start + req.Size;
mem.CardOffset = 0; mem.Page = 0;
@@ -3817,7 +3858,7 @@
/* Feed device with this info... */
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
+ netif_start_queue(dev);
#ifdef DEBUG_CONFIG_INFO
printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART 0x%x IRQ %d IOPORT 0x%x\n",
@@ -3843,7 +3884,7 @@
return FALSE;
}
- /* XXX Could you explain me this, Dave ? */
+ strcpy(((net_local *) dev->priv)->node.dev_name, dev->name);
link->dev = &((net_local *) dev->priv)->node;
#ifdef DEBUG_CONFIG_TRACE
@@ -3887,7 +3928,7 @@
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING | DEV_STALE_CONFIG);
+ link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG);
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
@@ -3896,7 +3937,7 @@
/*------------------------------------------------------------------*/
/*
- * Sometimes, netwave_detach can't be performed following a call from
+ * Sometimes, wavelan_detach can't be performed following a call from
* cardmgr (device still open, pcmcia_release not done) and the device
* is put in a STALE_LINK state and remains in memory.
*
@@ -3970,7 +4011,19 @@
lp = (net_local *) dev->priv;
base = dev->base_addr;
- spin_lock (&lp->lock);
+#ifdef DEBUG_INTERRUPT_INFO
+ /* Check state of our spinlock (it should be cleared) */
+ if(spin_is_locked(&lp->spinlock))
+ printk(KERN_DEBUG
+ "%s: wavelan_interrupt(): spinlock is already locked !!!\n",
+ dev->name);
+#endif
+
+ /* Prevent reentrancy. We need to do that because we may have
+ * multiple interrupt handler running concurently.
+ * It is safe because wv_splhi() disable interrupts before aquiring
+ * the spinlock. */
+ spin_lock(&lp->spinlock);
/* Treat all pending interrupts */
while(1)
@@ -4015,8 +4068,6 @@
break;
}
- lp->status = status0; /* Save current status (for commands) */
-
/* ----------------- RECEIVING PACKET ----------------- */
/*
* When the wavelan signal the reception of a new packet,
@@ -4054,22 +4105,6 @@
* Most likely : transmission done
*/
- /* If we are already waiting elsewhere for the command to complete */
- if(wv_wait_completed)
- {
-#ifdef DEBUG_INTERRUPT_INFO
- printk(KERN_DEBUG "%s: wv_interrupt(): command completed\n",
- dev->name);
-#endif
-
- /* Signal command completion */
- wv_wait_completed = 0;
-
- /* Acknowledge the interrupt */
- outb(CR0_INT_ACK | OP0_NOP, LCCR(base));
- continue;
- }
-
/* If a transmission has been done */
if((status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE ||
(status0 & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE ||
@@ -4081,10 +4116,6 @@
dev->name);
#endif
- /* If watchdog was activated, kill it ! */
- if(timer_pending(&lp->watchdog))
- del_timer(&lp->watchdog);
-
/* Get transmission status */
tx_status = inb(LCSR(base));
tx_status |= (inb(LCSR(base)) << 8);
@@ -4174,7 +4205,7 @@
lp->stats.collisions += (tx_status & TX_NCOL_MASK);
lp->stats.tx_packets++;
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */
}
else /* if interrupt = transmit done or retransmit done */
@@ -4185,9 +4216,9 @@
#endif
outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */
}
- }
+ } /* while(1) */
- spin_unlock_irq (&lp->lock);
+ spin_unlock(&lp->spinlock);
#ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
@@ -4196,30 +4227,23 @@
/*------------------------------------------------------------------*/
/*
- * Watchdog : when we start a transmission, we set a timer in the
- * kernel. If the transmission complete, this timer is disabled. If
- * it expire, it try to unlock the hardware.
+ * Watchdog: when we start a transmission, a timer is set for us in the
+ * kernel. If the transmission completes, this timer is disabled. If
+ * the timer expires, we are called and we try to unlock the hardware.
*
- * Note : this watchdog doesn't work on the same principle as the
- * watchdog in the ISA driver. I make it this way because the overhead
- * of add_timer() and del_timer() is nothing and that it avoid calling
- * the watchdog, saving some CPU... If you want to apply the same
- * watchdog to the ISA driver, you should be a bit carefull, because
- * of the many transmit buffers...
- * This watchdog is also move clever, it try to abort the current
- * command before reseting everything...
+ * Note : This watchdog is move clever than the one in the ISA driver,
+ * because it try to abort the current command before reseting
+ * everything...
+ * On the other hand, it's a bit simpler, because we don't have to
+ * deal with the multiple Tx buffers...
*/
static void
-wavelan_watchdog(u_long a)
+wavelan_watchdog(device * dev)
{
- device * dev;
- net_local * lp;
- ioaddr_t base;
- int spin;
-
- dev = (device *) a;
- base = dev->base_addr;
- lp = (net_local *) dev->priv;
+ net_local * lp = (net_local *) dev->priv;
+ ioaddr_t base = dev->base_addr;
+ unsigned long flags;
+ int aborted = FALSE;
#ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
@@ -4230,21 +4254,21 @@
dev->name);
#endif
- /* We are waiting for command completion */
- wv_wait_completed = TRUE;
+ wv_splhi(lp, &flags);
/* Ask to abort the current command */
outb(OP0_ABORT, LCCR(base));
- /* Busy wait while the LAN controller executes the command.
- * Note : wv_wait_completed should be volatile */
- spin = 0;
- while(wv_wait_completed && (spin++ < 250))
- udelay(10);
-
- /* If the interrupt handler hasn't be called or invalid status */
- if((wv_wait_completed) ||
- ((lp->status & SR0_EVENT_MASK) != SR0_EXECUTION_ABORTED))
+ /* Wait for the end of the command (a bit hackish) */
+ if(wv_82593_cmd(dev, "wavelan_watchdog(): abort",
+ OP0_NOP | CR0_STATUS_3, SR0_EXECUTION_ABORTED))
+ aborted = TRUE;
+
+ /* Release spinlock here so that wv_hw_reset() can grab it */
+ wv_splx(lp, &flags);
+
+ /* Check if we were successful in aborting it */
+ if(!aborted)
{
/* It seem that it wasn't enough */
#ifdef DEBUG_INTERRUPT_ERROR
@@ -4269,7 +4293,7 @@
#endif
/* We are no more waiting for something... */
- netif_start_queue (dev);
+ netif_wake_queue(dev);
#ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
@@ -4322,7 +4346,7 @@
return FALSE;
if(!wv_ru_start(dev))
wv_hw_reset(dev); /* If problem : reset */
- netif_start_queue (dev);
+ netif_start_queue(dev);
/* Mark the device as used */
link->open++;
@@ -4348,7 +4372,6 @@
wavelan_close(device * dev)
{
dev_link_t * link = ((net_local *) dev->priv)->link;
- net_local * lp = (net_local *)dev->priv;
ioaddr_t base = dev->base_addr;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4356,8 +4379,6 @@
(unsigned int) dev);
#endif
- netif_stop_queue (dev);
-
/* If the device isn't open, then nothing to do */
if(!link->open)
{
@@ -4373,17 +4394,13 @@
wv_roam_cleanup(dev);
#endif /* WAVELAN_ROAMING */
- /* If watchdog was activated, kill it ! */
- if(timer_pending(&lp->watchdog))
- del_timer(&lp->watchdog);
-
link->open--;
MOD_DEC_USE_COUNT;
/* If the card is still present */
- if (netif_device_present(dev))
+ if(netif_running(dev))
{
- netif_stop_queue (dev);
+ netif_stop_queue(dev);
/* Stop receiving new messages and wait end of transmission */
wv_ru_stop(dev);
@@ -4404,21 +4421,6 @@
/*------------------------------------------------------------------*/
/*
- * We never need to do anything when a wavelan device is "initialized"
- * by the net software, because we only register already-found cards.
- */
-static int
-wavelan_init(device * dev)
-{
-#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "<>wavelan_init()\n");
-#endif
-
- return(0);
-}
-
-/*------------------------------------------------------------------*/
-/*
* wavelan_attach() creates an "instance" of the driver, allocating
* local data structures for one device (one interface). The device
* is registered with Card Services.
@@ -4445,24 +4447,8 @@
/* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return NULL;
-
- /* Allocate the generic data structure */
- dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if (!dev)
- goto fail_alloc_dev;
-
- /* Allocate the wavelan-specific data structure. */
- lp = (net_local *) kmalloc(sizeof(net_local), GFP_KERNEL);
- if (!lp)
- goto fail_alloc_dev_priv;
-
- memset(lp, 0, sizeof(net_local));
+ if (!link) return NULL;
memset(link, 0, sizeof(struct dev_link_t));
- memset(dev, 0, sizeof(struct net_device));
-
- dev->priv = lp;
/* Unused for the Wavelan */
link->release.function = &wv_pcmcia_release;
@@ -4492,18 +4478,35 @@
link->next = dev_list;
dev_list = link;
+ /* Allocate the generic data structure */
+ dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ if (!dev) {
+ kfree(link);
+ return NULL;
+ }
+ memset(dev, 0x00, sizeof(struct net_device));
link->priv = link->irq.Instance = dev;
+ /* Allocate the wavelan-specific data structure. */
+ dev->priv = lp = (net_local *) kmalloc(sizeof(net_local), GFP_KERNEL);
+ if (!lp) {
+ kfree(link);
+ kfree(dev);
+ return NULL;
+ }
+ memset(lp, 0x00, sizeof(net_local));
+
/* Init specific data */
- wv_wait_completed = 0;
- lp->status = FALSE;
lp->configured = 0;
lp->reconfig_82593 = FALSE;
lp->nresets = 0;
+ /* Multicast stuff */
+ lp->promiscuous = 0;
+ lp->allmulticast = 0;
+ lp->mc_count = 0;
- /* Set the watchdog timer */
- lp->watchdog.function = wavelan_watchdog;
- lp->watchdog.data = (unsigned long) dev;
+ /* Init spinlock */
+ spin_lock_init(&lp->spinlock);
/* back links */
lp->link = link;
@@ -4513,7 +4516,6 @@
ether_setup(dev);
/* wavelan NET3 callbacks */
- dev->init = &wavelan_init;
dev->open = &wavelan_open;
dev->stop = &wavelan_close;
dev->hard_start_xmit = &wavelan_packet_xmit;
@@ -4523,14 +4525,16 @@
dev->set_mac_address = &wavelan_set_mac_address;
#endif /* SET_MAC_ADDRESS */
+ /* Set the watchdog timer */
+ dev->tx_timeout = &wavelan_watchdog;
+ dev->watchdog_timeo = WATCHDOG_JIFFIES;
+
#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
dev->do_ioctl = wavelan_ioctl; /* wireless extensions */
dev->get_wireless_stats = wavelan_get_wireless_stats;
#endif
/* Other specific data */
- strcpy(dev->name, ((net_local *)dev->priv)->node.dev_name);
- netif_start_queue (dev);
dev->mtu = WAVELAN_MTU;
/* Register with Card Services */
@@ -4562,12 +4566,6 @@
#endif
return link;
-
-fail_alloc_dev_priv:
- kfree(dev);
-fail_alloc_dev:
- kfree(link);
- return NULL;
}
/*------------------------------------------------------------------*/
@@ -4698,7 +4696,7 @@
if(link->state & DEV_CONFIG)
{
/* Accept no more transmissions */
- netif_device_detach(dev);
+ netif_device_detach(dev);
/* Release the card */
wv_pcmcia_release((u_long) link);
@@ -4720,7 +4718,7 @@
* obliged to close nicely the wavelan here. David, could you
* close the device before suspending them ? And, by the way,
* could you, on resume, add a "route add -net ..." after the
- * ifconfig up XXX Thanks... */
+ * ifconfig up ??? Thanks... */
/* Stop receiving new messages and wait end of transmission */
wv_ru_stop(dev);
@@ -4735,8 +4733,7 @@
if(link->state & DEV_CONFIG)
{
if(link->open)
- netif_device_detach(dev);
-
+ netif_device_detach(dev);
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -4748,7 +4745,7 @@
if(link->state & DEV_CONFIG)
{
CardServices(RequestConfiguration, link->handle, &link->conf);
- if(link->open) /* If RESET -> True, If RESUME -> False XXX */
+ if(link->open) /* If RESET -> True, If RESUME -> False ??? */
{
wv_hw_reset(dev);
netif_device_attach(dev);
@@ -4838,4 +4835,3 @@
module_init(init_wavelan_cs);
module_exit(exit_wavelan_cs);
-MODULE_LICENSE("Dual BSD/GPL");
diff -u --recursive --new-file pre1/linux/drivers/net/pcmcia/wavelan_cs.h linux/drivers/net/pcmcia/wavelan_cs.h
--- pre1/linux/drivers/net/pcmcia/wavelan_cs.h Fri Oct 12 14:21:18 2001
+++ linux/drivers/net/pcmcia/wavelan_cs.h Tue Jan 15 18:54:35 2002
@@ -34,6 +34,25 @@
* I try to maintain a web page with the Wireless LAN Howto at :
* http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Wavelan.html
*
+ * SMP
+ * ---
+ * We now are SMP compliant (I eventually fixed the remaining bugs).
+ * The driver has been tested on a dual P6-150 and survived my usual
+ * set of torture tests.
+ * Anyway, I spent enough time chasing interrupt re-entrancy during
+ * errors or reconfigure, and I designed the locked/unlocked sections
+ * of the driver with great care, and with the recent addition of
+ * the spinlock (thanks to the new API), we should be quite close to
+ * the truth.
+ * The SMP/IRQ locking is quite coarse and conservative (i.e. not fast),
+ * but better safe than sorry (especially at 2 Mb/s ;-).
+ *
+ * I have also looked into disabling only our interrupt on the card
+ * (via HACR) instead of all interrupts in the processor (via cli),
+ * so that other driver are not impacted, and it look like it's
+ * possible, but it's very tricky to do right (full of races). As
+ * the gain would be mostly for SMP systems, it can wait...
+ *
* Debugging and options
* ---------------------
* You will find below a set of '#define" allowing a very fine control
@@ -122,7 +141,7 @@
* Yunzhou Li finished is work.
* Joe Finney patched the driver to start
* correctly 2.00 cards (2.4 GHz with frequency selection).
- * David Hinds integrated the whole in his
+ * David Hinds integrated the whole in his
* Pcmcia package (+ bug corrections).
*
* I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some
@@ -158,8 +177,8 @@
*
* This software was originally developed under Linux 1.2.3
* (Slackware 2.0 distribution).
- * And then under Linux 2.0.x (Debian 1.1 - pcmcia 2.8.18-23) with
- * HP OmniBook 4000 & 5500.
+ * And then under Linux 2.0.x (Debian 1.1 -> 2.2 - pcmcia 2.8.18+)
+ * with an HP OmniBook 4000 and then a 5500.
*
* It is based on other device drivers and information either written
* or supplied by:
@@ -174,7 +193,7 @@
* Matthew Geier (matthew@cs.su.oz.au),
* Remo di Giovanni (remo@cs.su.oz.au),
* Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM),
- * David Hinds ,
+ * David Hinds ,
* Jan Hoogendoorn (c/o marteijn@lucent.com),
* Bruce Janson ,
* Anthony D. Joseph ,
@@ -349,6 +368,32 @@
* - Fix check for root permission (break instead of exit)
* - New nwid & encoding setting (Wireless Extension 9)
*
+ * Changes made for release in 3.1.12 :
+ * ----------------------------------
+ * - reworked wv_82593_cmd to avoid using the IRQ handler and doing
+ * ugly things with interrupts.
+ * - Add IRQ protection in 82593_config/ru_start/ru_stop/watchdog
+ * - Update to new network API (softnet - 2.3.43) :
+ * o replace dev->tbusy (David + me)
+ * o replace dev->tstart (David + me)
+ * o remove dev->interrupt (David)
+ * o add SMP locking via spinlock in splxx (me)
+ * o add spinlock in interrupt handler (me)
+ * o use kernel watchdog instead of ours (me)
+ * o verify that all the changes make sense and work (me)
+ * - Re-sync kernel/pcmcia versions (not much actually)
+ * - A few other cleanups (David & me)...
+ *
+ * Changes made for release in 3.1.22 :
+ * ----------------------------------
+ * - Check that SMP works, remove annoying log message
+ *
+ * Changes made for release in 3.1.24 :
+ * ----------------------------------
+ * - Fix unfrequent card lockup when watchdog was reseting the hardware :
+ * o control first busy loop in wv_82593_cmd()
+ * o Extend spinlock protection in wv_hw_config()
+ *
* Wishes & dreams:
* ----------------
* - Cleanup and integrate the roaming code
@@ -368,6 +413,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -384,7 +430,7 @@
#ifdef CONFIG_NET_PCMCIA_RADIO
#include /* Wireless extensions */
-#endif /* CONFIG_NET_PCMCIA_RADIO */
+#endif
/* Pcmcia headers that we need */
#include
@@ -437,7 +483,7 @@
#undef DEBUG_RX_INFO /* Header of the transmitted packet */
#undef DEBUG_RX_FAIL /* Normal failure conditions */
#define DEBUG_RX_ERROR /* Unexpected conditions */
-#undef DEBUG_PACKET_DUMP /* Dump packet on the screen */
+#undef DEBUG_PACKET_DUMP 32 /* Dump packet on the screen */
#undef DEBUG_IOCTL_TRACE /* Misc call by Linux */
#undef DEBUG_IOCTL_INFO /* Various debug info */
#define DEBUG_IOCTL_ERROR /* What's going wrong */
@@ -452,7 +498,7 @@
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan_cs.c : v21 (wireless extensions) 18/10/99\n";
+static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/12/00\n";
#endif
/* Watchdog temporisation */
@@ -557,9 +603,9 @@
*/
struct net_local
{
- spinlock_t lock;
dev_node_t node; /* ???? What is this stuff ???? */
device * dev; /* Reverse link... */
+ spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
dev_link_t * link; /* pcmcia structure */
en_stats stats; /* Ethernet interface statistics */
int nresets; /* Number of hw resets */
@@ -568,9 +614,7 @@
u_char promiscuous; /* Promiscuous mode */
u_char allmulticast; /* All Multicast mode */
int mc_count; /* Number of multicast addresses */
- timer_list watchdog; /* To avoid blocking state */
- u_char status; /* Current i82593 status */
int stop; /* Current i82593 Stop Hit Register */
int rfp; /* Last DMA machine receive pointer */
int overrunning; /* Receiver overrun flag */
@@ -617,8 +661,14 @@
#endif /* WAVELAN_ROAMING */
/* ----------------------- MISC SUBROUTINES ------------------------ */
+static inline void
+ wv_splhi(net_local *, /* Disable interrupts */
+ unsigned long *); /* flags */
+static inline void
+ wv_splx(net_local *, /* ReEnable interrupts */
+ unsigned long *); /* flags */
static void
- cs_error(client_handle_t, /* Report error to cardmgr */
+ cs_error(client_handle_t, /* Report error to cardmgr */
int,
int);
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
@@ -722,16 +772,15 @@
wv_flush_stale_links(void); /* "detach" all possible devices */
/* ---------------------- INTERRUPT HANDLING ---------------------- */
static void
-wavelan_interrupt(int, /* Interrupt handler */
- void *,
- struct pt_regs *);
+ wavelan_interrupt(int, /* Interrupt handler */
+ void *,
+ struct pt_regs *);
static void
- wavelan_watchdog(u_long); /* Transmission watchdog */
+ wavelan_watchdog(device *); /* Transmission watchdog */
/* ------------------- CONFIGURATION CALLBACKS ------------------- */
static int
wavelan_open(device *), /* Open the device */
- wavelan_close(device *), /* Close the device */
- wavelan_init(device *); /* Do nothing */
+ wavelan_close(device *); /* Close the device */
static dev_link_t *
wavelan_attach(void); /* Create a new device */
static void
@@ -744,11 +793,7 @@
/**************************** VARIABLES ****************************/
static dev_info_t dev_info = "wavelan_cs";
-static dev_link_t *dev_list; /* Linked list of devices */
-
-/* WARNING : the following variable MUST be volatile
- * It is used by wv_82593_cmd to syncronise with wavelan_interrupt */
-static volatile int wv_wait_completed;
+static dev_link_t *dev_list = NULL; /* Linked list of devices */
/*
* Parameters that can be set with 'insmod'
@@ -761,7 +806,7 @@
static int irq_list[4] = { -1 };
/* Shared memory speed, in ns */
-static int mem_speed;
+static int mem_speed = 0;
/* New module interface */
MODULE_PARM(irq_mask, "i");
@@ -770,9 +815,11 @@
#ifdef WAVELAN_ROAMING /* Conditional compile, see above in options */
/* Enable roaming mode ? No ! Please keep this to 0 */
-static int do_roaming;
+static int do_roaming = 0;
MODULE_PARM(do_roaming, "i");
#endif /* WAVELAN_ROAMING */
+
+MODULE_LICENSE("GPL");
#endif /* WAVELAN_CS_H */
diff -u --recursive --new-file pre1/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c
--- pre1/linux/drivers/nubus/nubus.c Wed Jun 27 17:10:55 2001
+++ linux/drivers/nubus/nubus.c Thu Jan 17 14:21:16 2002
@@ -1039,3 +1039,5 @@
nubus_proc_init();
#endif
}
+
+subsys_initcall(nubus_init);
diff -u --recursive --new-file pre1/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- pre1/linux/drivers/parport/ChangeLog Wed Jan 16 11:16:28 2002
+++ linux/drivers/parport/ChangeLog Thu Jan 17 14:07:57 2002
@@ -1,3 +1,23 @@
+2001-12-07 Tim Waugh
+
+ * ieee1284_ops.c (parport_ieee1284_epp_write_addr,
+ parport_ieee1284_epp_read_addr): Actually do something useful.
+
+2001-12-07 Tim Waugh
+
+ * parport_pc.c (dmaval): Don't use DMA by default. It seems to be
+ too buggy at the moment. Use 'dma=auto' to restore the previous
+ behaviour.
+
+2001-12-03 Rich Liu
+
+ * parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
+ serial board, not a serial+parallel.
+
+2001-11-30 Niels Kristian Bech Jensen
+
+ * parport_pc.c: Fix compiler warning.
+
2001-12-06 Tim Waugh
* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
diff -u --recursive --new-file pre1/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c
--- pre1/linux/drivers/parport/ieee1284.c Thu Oct 25 00:07:39 2001
+++ linux/drivers/parport/ieee1284.c Tue Jan 15 13:53:51 2002
@@ -128,7 +128,7 @@
return 0;
if (signal_pending (current))
return -EINTR;
- if (current->need_resched)
+ if (need_resched())
break;
if (i >= 2)
udelay (5);
diff -u --recursive --new-file pre1/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- pre1/linux/drivers/parport/ieee1284_ops.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/parport/ieee1284_ops.c Thu Jan 17 14:07:57 2002
@@ -136,7 +136,7 @@
/* Let another process run if it needs to. */
if (time_before (jiffies, expire))
if (!parport_yield_blocking (dev)
- && current->need_resched)
+ && need_resched())
schedule ();
}
stop:
@@ -824,35 +824,40 @@
const void *buffer, size_t len,
int flags)
{
- /* This is untested */
unsigned char *bp = (unsigned char *) buffer;
size_t ret = 0;
+ /* set EPP idle state (just to make sure) with strobe low */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
- PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_INIT,
PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_SELECT);
+ PARPORT_CONTROL_INIT);
port->ops->data_forward (port);
for (; len > 0; len--, bp++) {
- /* Write data and assert nAStrb. */
+ /* Event 56: Write data and set nAStrb low. */
parport_write_data (port, *bp);
parport_frob_control (port, PARPORT_CONTROL_SELECT,
PARPORT_CONTROL_SELECT);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
- PARPORT_STATUS_BUSY, 10))
+ /* Event 58: wait for busy (nWait) to go high */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
break;
+ /* Event 59: set nAStrb high */
parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+ /* Event 60: wait for busy (nWait) to go low */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+ PARPORT_STATUS_BUSY, 5))
break;
ret++;
}
+ /* Event 61: set strobe (nWrite) high */
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
return ret;
@@ -863,28 +868,36 @@
void *buffer, size_t len,
int flags)
{
- /* This is untested. */
unsigned char *bp = (unsigned char *) buffer;
unsigned ret = 0;
+ /* Set EPP idle state (just to make sure) with strobe high */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD, 0);
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_SELECT |
+ PARPORT_CONTROL_INIT,
+ PARPORT_CONTROL_INIT);
port->ops->data_reverse (port);
for (; len > 0; len--, bp++) {
- parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+ /* Event 64: set nSelectIn (nAStrb) low */
+ parport_frob_control (port, PARPORT_CONTROL_SELECT,
+ PARPORT_CONTROL_SELECT);
- /* Event 58 */
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
- PARPORT_STATUS_BUSY, 10))
+ /* Event 58: wait for Busy to go high */
+ if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
break;
+ }
*bp = parport_read_data (port);
+ /* Event 59: set nSelectIn (nAStrb) high */
parport_frob_control (port, PARPORT_CONTROL_SELECT,
PARPORT_CONTROL_SELECT);
- if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+ /* Event 60: wait for Busy to go low */
+ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+ PARPORT_STATUS_BUSY, 5))
break;
ret++;
diff -u --recursive --new-file pre1/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- pre1/linux/drivers/parport/parport_pc.c Mon Nov 12 09:44:58 2001
+++ linux/drivers/parport/parport_pc.c Thu Jan 17 14:07:57 2002
@@ -91,7 +91,9 @@
} superios[NR_SUPERIOS] __devinitdata = { {0,},};
static int user_specified __devinitdata = 0;
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
static int verbose_probing;
+#endif
static int registered_parport;
/* frob_control, but for ECR */
@@ -596,7 +598,7 @@
unsigned char ecrval = inb (ECONTROL (port));
int i = 0;
- if (current->need_resched && time_before (jiffies, expire))
+ if (need_resched() && time_before (jiffies, expire))
/* Can't yield the port. */
schedule ();
@@ -622,7 +624,7 @@
}
ecrval = inb (ECONTROL (port));
if (!(ecrval & (1<<2))) {
- if (current->need_resched &&
+ if (need_resched() &&
time_before (jiffies, expire))
schedule ();
@@ -746,8 +748,7 @@
}
/* Is serviceIntr set? */
if (!(inb (ECONTROL (port)) & (1<<2))) {
- if (current->need_resched)
- schedule ();
+ cond_resched();
goto false_alarm;
}
@@ -758,9 +759,7 @@
count = get_dma_residue(port->dma);
release_dma_lock(dmaflag);
- if (current->need_resched)
- /* Can't yield the port. */
- schedule ();
+ cond_resched(); /* Can't yield the port. */
/* Anyone else waiting for the port? */
if (port->waithead) {
@@ -1093,7 +1092,7 @@
long int expire = jiffies + port->cad->timeout;
unsigned char ecrval = inb (ECONTROL (port));
- if (current->need_resched && time_before (jiffies, expire))
+ if (need_resched() && time_before (jiffies, expire))
/* Can't yield the port. */
schedule ();
@@ -1130,7 +1129,7 @@
}
ecrval = inb (ECONTROL (port));
if (!(ecrval & (1<<2))) {
- if (current->need_resched &&
+ if (need_resched() &&
time_before (jiffies, expire)) {
schedule ();
}
@@ -1780,6 +1779,7 @@
return ok;
}
+#ifdef CONFIG_PARPORT_PC_FIFO
static int __devinit parport_ECP_supported(struct parport *pb)
{
int i;
@@ -1905,6 +1905,7 @@
return 1;
}
+#endif
static int __devinit parport_ECPPS2_supported(struct parport *pb)
{
@@ -2004,7 +2005,9 @@
/* Don't bother probing for modes we know we won't use. */
static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }
+#ifdef CONFIG_PARPORT_PC_FIFO
static int __devinit parport_ECP_supported(struct parport *pb) { return 0; }
+#endif
static int __devinit parport_EPP_supported(struct parport *pb) { return 0; }
static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}
static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}
@@ -2453,9 +2456,8 @@
ite8872set = 0x64e00000;
break;
case 0x6:
- printk (KERN_INFO "parport_pc: ITE8873 found (1S1P)\n");
- ite8872set = 0x64a00000;
- break;
+ printk (KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+ return 0;
case 0x8:
DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n");
return 0;
@@ -3007,7 +3009,7 @@
static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
static int io_hi[PARPORT_PC_MAX_PORTS+1] =
{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
-static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
@@ -3024,8 +3026,10 @@
MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
MODULE_PARM_DESC(dma, "DMA channel");
MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-MODULE_PARM(verbose_probing, "i");
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
+MODULE_PARM(verbose_probing, "i");
+#endif
int init_module(void)
{
diff -u --recursive --new-file pre1/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- pre1/linux/drivers/pci/pci.c Tue Nov 20 21:53:29 2001
+++ linux/drivers/pci/pci.c Thu Jan 17 14:21:16 2002
@@ -1929,7 +1929,7 @@
}
-void __devinit pci_init(void)
+static int __devinit pci_init(void)
{
struct pci_dev *dev;
@@ -1942,6 +1942,7 @@
#ifdef CONFIG_PM
pm_register(PM_PCI_DEV, 0, pci_pm_callback);
#endif
+ return 0;
}
static int __devinit pci_setup(char *str)
@@ -1958,6 +1959,8 @@
}
return 1;
}
+
+subsys_initcall(pci_init);
__setup("pci=", pci_setup);
diff -u --recursive --new-file pre1/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- pre1/linux/drivers/pcmcia/ds.c Tue Jan 1 11:51:31 2002
+++ linux/drivers/pcmcia/ds.c Thu Jan 17 14:21:16 2002
@@ -966,12 +966,9 @@
return 0;
}
-#ifdef MODULE
+late_initcall(init_pcmcia_ds);
-int __init init_module(void)
-{
- return init_pcmcia_ds();
-}
+#ifdef MODULE
void __exit cleanup_module(void)
{
diff -u --recursive --new-file pre1/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- pre1/linux/drivers/pnp/isapnp.c Mon Nov 12 10:02:54 2001
+++ linux/drivers/pnp/isapnp.c Thu Jan 17 14:21:16 2002
@@ -2356,12 +2356,9 @@
return 0;
}
-#ifdef MODULE
+subsys_initcall(isapnp_init);
-int init_module(void)
-{
- return isapnp_init();
-}
+#ifdef MODULE
void cleanup_module(void)
{
diff -u --recursive --new-file pre1/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- pre1/linux/drivers/sbus/sbus.c Mon Jan 14 10:10:44 2002
+++ linux/drivers/sbus/sbus.c Thu Jan 17 14:21:16 2002
@@ -509,3 +509,5 @@
}
#endif
}
+
+subsys_initcall(sbus_init);
diff -u --recursive --new-file pre1/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- pre1/linux/drivers/scsi/advansys.c Thu Jan 10 10:15:38 2002
+++ linux/drivers/scsi/advansys.c Thu Jan 17 13:59:33 2002
@@ -1,4 +1,4 @@
-#define ASC_VERSION "3.3G" /* AdvanSys Driver Version */
+#define ASC_VERSION "3.3GG" /* AdvanSys Driver Version */
/*
* advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
@@ -670,6 +670,9 @@
1. Return an error from narrow boards if passed a 16 byte
CDB. The wide board can already handle 16 byte CDBs.
+ 3.3GG (01/02/02):
+ 1. hacks for lk 2.5 series (D. Gilbert)
+
I. Known Problems/Fix List (XXX)
1. Need to add memory mapping workaround. Test the memory mapping.
@@ -3610,6 +3613,23 @@
#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* CONFIG_PROC_FS */
+/*
+ * XXX - Release and acquire the io_request_lock. These macros are needed
+ * because the 2.4 kernel SCSI mid-level driver holds the 'io_request_lock'
+ * on entry to SCSI low-level drivers.
+ *
+ * These definitions and all code that uses code should be removed when the
+ * SCSI mid-level driver no longer holds the 'io_request_lock' on entry to
+ * SCSI low-level driver detect, queuecommand, and reset entrypoints.
+ *
+ * The interrupt flags values doesn't matter in the macros because the
+ * SCSI mid-level will save and restore the flags values before and after
+ * calling advansys_detect, advansys_queuecommand, and advansys_reset where
+ * these macros are used. We do want interrupts enabled after the lock is
+ * released so an explicit sti() is done. The driver only needs interrupts
+ * disabled when it acquires the per board lock.
+ */
+
/* Asc Library return codes */
#define ASC_TRUE 1
#define ASC_FALSE 0
@@ -4054,6 +4074,7 @@
ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
} eep_config;
ulong last_reset; /* Saved last reset time */
+ spinlock_t lock; /* Board spinlock */
#ifdef CONFIG_PROC_FS
/* /proc/scsi/advansys/[0...] */
char *prtbuf; /* /proc print buffer */
@@ -4206,7 +4227,7 @@
STATIC void advansys_interrupt(int, void *, struct pt_regs *);
STATIC void advansys_select_queue_depths(struct Scsi_Host *,
Scsi_Device *);
-STATIC void asc_scsi_done_list(Scsi_Cmnd *);
+STATIC void asc_scsi_done_list(Scsi_Cmnd *, int from_isr);
STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *);
STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
@@ -4799,6 +4820,9 @@
memset(boardp, 0, sizeof(asc_board_t));
boardp->id = asc_board_count - 1;
+ /* Initialize spinlock. */
+ boardp->lock = SPIN_LOCK_UNLOCKED; /* replaced by host_lock dpg */
+
/*
* Handle both narrow and wide boards.
*
@@ -5511,7 +5535,7 @@
}
} else {
ADV_CARR_T *carrp;
- int req_cnt;
+ int req_cnt = 0;
adv_req_t *reqp = NULL;
int sg_cnt = 0;
@@ -5845,7 +5869,9 @@
boardp = ASC_BOARDP(shp);
ASC_STATS(shp, queuecommand);
- spin_lock_irqsave(&shp->host_lock, flags);
+ /* host_lock taken by mid-level prior to call but need to protect */
+ /* against own ISR */
+ spin_lock_irqsave(&boardp->lock, flags);
/*
* Block new commands while handling a reset or abort request.
@@ -5862,7 +5888,7 @@
* handling.
*/
asc_enqueue(&boardp->done, scp, ASC_BACK);
- spin_unlock_irqrestore(&shp->host_lock, flags);
+ spin_unlock_irqrestore(&boardp->lock, flags);
return 0;
}
@@ -5902,11 +5928,11 @@
default:
done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
/* Interrupts could be enabled here. */
- asc_scsi_done_list(done_scp);
+ asc_scsi_done_list(done_scp, 0);
break;
}
+ spin_unlock_irqrestore(&boardp->lock, flags);
- spin_unlock_irqrestore(&shp->host_lock, flags);
return 0;
}
@@ -5952,13 +5978,13 @@
/*
* Check for re-entrancy.
*/
- spin_lock_irqsave(&shp->host_lock, flags);
+ spin_lock_irqsave(&boardp->lock, flags);
if (boardp->flags & ASC_HOST_IN_RESET) {
- spin_unlock_irqrestore(&shp->host_lock, flags);
+ spin_unlock_irqrestore(&boardp->lock, flags);
return FAILED;
}
boardp->flags |= ASC_HOST_IN_RESET;
- spin_unlock_irqrestore(&shp->host_lock, flags);
+ spin_unlock_irqrestore(&boardp->lock, flags);
if (ASC_NARROW_BOARD(boardp)) {
/*
@@ -5989,11 +6015,7 @@
}
ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
-
- /*
- * Acquire the board lock.
- */
- spin_lock_irqsave(&shp->host_lock, flags);
+ spin_lock_irqsave(&boardp->lock, flags);
} else {
/*
@@ -6020,14 +6042,9 @@
ret = FAILED;
break;
}
- /*
- * Acquire the board lock and ensure all requests completed by the
- * microcode have been processed by calling AdvISR().
- */
- spin_lock_irqsave(&shp->host_lock, flags);
+ spin_lock_irqsave(&boardp->lock, flags);
(void) AdvISR(adv_dvc_varp);
}
-
/* Board lock is held. */
/*
@@ -6088,15 +6105,13 @@
/* Clear reset flag. */
boardp->flags &= ~ASC_HOST_IN_RESET;
-
- /* Release the board. */
- spin_unlock_irqrestore(&shp->host_lock, flags);
+ spin_unlock_irqrestore(&boardp->lock, flags);
/*
* Complete all the 'done_scp' requests.
*/
if (done_scp != NULL) {
- asc_scsi_done_list(done_scp);
+ asc_scsi_done_list(done_scp, 0);
}
ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
@@ -6259,6 +6274,7 @@
asc_board_t *boardp;
Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
Scsi_Cmnd *new_last_scp;
+ struct Scsi_Host *shp;
ASC_DBG(1, "advansys_interrupt: begin\n");
@@ -6267,17 +6283,17 @@
* AscISR() will call asc_isr_callback().
*/
for (i = 0; i < asc_board_count; i++) {
- struct Scsi_Host *shp = asc_host[i];
+ shp = asc_host[i];
boardp = ASC_BOARDP(shp);
ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
i, (ulong) boardp);
- spin_lock_irqsave(&shp->host_lock, flags);
+ spin_lock_irqsave(&boardp->lock, flags);
if (ASC_NARROW_BOARD(boardp)) {
/*
* Narrow Board
*/
- if (AscIsIntPending(asc_host[i]->io_port)) {
- ASC_STATS(asc_host[i], interrupt);
+ if (AscIsIntPending(shp->io_port)) {
+ ASC_STATS(shp, interrupt);
ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
AscISR(&boardp->dvc_var.asc_dvc_var);
}
@@ -6287,7 +6303,7 @@
*/
ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
- ASC_STATS(asc_host[i], interrupt);
+ ASC_STATS(shp, interrupt);
}
}
@@ -6327,7 +6343,7 @@
}
}
}
- spin_unlock_irqrestore(&shp->host_lock, flags);
+ spin_unlock_irqrestore(&boardp->lock, flags);
}
/*
@@ -6336,7 +6352,8 @@
*
* Complete all requests on the done list.
*/
- asc_scsi_done_list(done_scp);
+
+ asc_scsi_done_list(done_scp, 1);
ASC_DBG(1, "advansys_interrupt: end\n");
return;
@@ -6383,9 +6400,10 @@
* Interrupts can be enabled on entry.
*/
STATIC void
-asc_scsi_done_list(Scsi_Cmnd *scp)
+asc_scsi_done_list(Scsi_Cmnd *scp, int from_isr)
{
Scsi_Cmnd *tscp;
+ ulong flags = 0;
ASC_DBG(2, "asc_scsi_done_list: begin\n");
while (scp != NULL) {
@@ -6394,7 +6412,11 @@
REQPNEXT(scp) = NULL;
ASC_STATS(scp->host, done);
ASC_ASSERT(scp->scsi_done != NULL);
+ if (from_isr)
+ spin_lock_irqsave(&scp->host->host_lock, flags);
scp->scsi_done(scp);
+ if (from_isr)
+ spin_unlock_irqrestore(&scp->host->host_lock, flags);
scp = tscp;
}
ASC_DBG(2, "asc_scsi_done_list: done\n");
@@ -6728,7 +6750,9 @@
slp = (struct scatterlist *) scp->request_buffer;
for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
asc_sg_head.sg_list[sgcnt].addr =
- cpu_to_le32(virt_to_bus(slp->address));
+ cpu_to_le32(virt_to_bus(slp->address ?
+ (unsigned char *)slp->address :
+ (unsigned char *)page_address(slp->page) + slp->offset));
asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length);
ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
}
@@ -6986,7 +7010,9 @@
for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
{
sg_block->sg_list[i].sg_addr =
- cpu_to_le32(virt_to_bus(slp->address));
+ cpu_to_le32(virt_to_bus(slp->address ?
+ (unsigned char *)slp->address :
+ (unsigned char *)page_address(slp->page) + slp->offset));
sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length);
ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
diff -u --recursive --new-file pre1/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- pre1/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c Thu Jan 10 10:15:38 2002
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c Thu Jan 17 13:59:33 2002
@@ -1700,6 +1700,7 @@
cmd->request_buffer,
cmd->request_bufflen,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
+ scb->sg_count = 0;
scb->sg_count = ahc_linux_map_seg(ahc, scb,
sg, addr,
cmd->request_bufflen);
diff -u --recursive --new-file pre1/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- pre1/linux/drivers/scsi/scsi_debug.c Sun Dec 16 12:20:20 2001
+++ linux/drivers/scsi/scsi_debug.c Thu Jan 17 13:59:33 2002
@@ -3,8 +3,19 @@
*
* Copyright (C) 1992 Eric Youngdale
* Simulate a host adapter with 2 disks attached. Do a lot of checking
- * to make sure that we are not getting blocks mixed up, and panic if
+ * to make sure that we are not getting blocks mixed up, and PANIC if
* anything out of the ordinary is seen.
+ *
+ * This version is more generic, simulating a variable number of disk
+ * (or disk like devices) sharing a common amount of RAM (default 8 MB
+ * but can be set at driver/module load time).
+ *
+ * For documentation see http://www.torque.net/sg/sdebug.html
+ *
+ * D. Gilbert (dpg) work for MOD device test [20010421]
+ * dpg, work for devfs large number of disks [20010809]
+ * dpg, make more generic [20011123]
+ * dpg, forked for lk 2.5 series [20011216, 20020101]
*/
#include
@@ -18,7 +29,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
@@ -27,201 +40,187 @@
#include "scsi.h"
#include "hosts.h"
-#include "sd.h"
-
#include
-/* A few options that we want selected */
+#ifndef LINUX_VERSION_CODE
+#include
+#endif
+
+static char scsi_debug_version_str[] = "Version: 1.57 (20011216)";
-#define NR_HOSTS_PRESENT 1
-#define NR_FAKE_DISKS 3
-#define N_HEAD 255
-#define N_SECTOR 63
-#define N_CYLINDER 524
+#ifndef SCSI_CMD_READ_16
+#define SCSI_CMD_READ_16 0x88
+#endif
+#ifndef SCSI_CMD_WRITE_16
+#define SCSI_CMD_WRITE_16 0x8a
+#endif
+
+/* A few options that we want selected */
+#define DEF_NR_FAKE_DEVS 1
+#define DEF_DEV_SIZE_MB 8
+#define DEF_FAKE_BLK0 0
+
+static int scsi_debug_num_devs = DEF_NR_FAKE_DEVS;
+
+#define NR_HOSTS_PRESENT (((scsi_debug_num_devs - 1) / 7) + 1)
+#define N_HEAD 8
+#define N_SECTOR 32
#define DISK_READONLY(TGT) (0)
-#define DISK_REMOVEABLE(TGT) (1)
-#define DEVICE_TYPE(TGT) (TGT == 2 ? TYPE_TAPE : TYPE_DISK);
+#define DISK_REMOVEABLE(TGT) (0)
+#define DEVICE_TYPE(TGT) (TYPE_DISK);
+
+#define SCSI_DEBUG_MAILBOXES (scsi_debug_num_devs + 1)
+
+static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
+#define STORE_SIZE (scsi_debug_dev_size_mb * 1024 * 1024)
+#define STORE_ELEM_ORDER 1
+#define STORE_ELEM_SIZE (PAGE_SIZE * (1 << STORE_ELEM_ORDER))
+#define STORE_ELEMENTS ((STORE_SIZE / STORE_ELEM_SIZE) + 1)
+
+/* default sector size is 512 bytes, 2**9 bytes */
+#define POW2_SECT_SIZE 9
+#define SECT_SIZE (1 << POW2_SECT_SIZE)
+
+#define N_CYLINDER (STORE_SIZE / (SECT_SIZE * N_SECTOR * N_HEAD))
+
+static int scsi_debug_fake_blk0 = DEF_FAKE_BLK0;
/* Do not attempt to use a timer to simulate a real disk with latency */
/* Only use this in the actual kernel, not in the simulator. */
#define IMMEDIATE
-/* Skip some consistency checking. Good for benchmarking */
-#define SPEEDY
-/* Read return zeros. Undefine for benchmarking */
-#define CLEAR
-
-/* Number of real scsi disks that will be detected ahead of time */
-static int NR_REAL = -1;
-
-#define NR_BLK_DEV 12
-#ifndef MAJOR_NR
-#define MAJOR_NR 8
-#endif
+#define SDEBUG_SG_ADDRESS
+
#define START_PARTITION 4
/* Time to wait before completing a command */
#define DISK_SPEED (HZ/10) /* 100ms */
#define CAPACITY (N_HEAD * N_SECTOR * N_CYLINDER)
-#define SIZE(TGT) (TGT == 2 ? 2248 : 512)
+#define SECT_SIZE_PER(TGT) SECT_SIZE
+#define SECT_PER_ELEM (STORE_ELEM_SIZE / SECT_SIZE)
static int starts[] =
{N_SECTOR,
N_HEAD * N_SECTOR, /* Single cylinder */
N_HEAD * N_SECTOR * 4,
- CAPACITY, 0};
+ 0 /* CAPACITY */, 0};
static int npart = 0;
-#include "scsi_debug.h"
-#ifdef DEBUG
-#define DEB(x) x
-#else
-#define DEB(x)
-#endif
+typedef struct scsi_debug_store_elem {
+ unsigned char * p;
+} Sd_store_elem;
+
+static Sd_store_elem * store_arr = 0;
+
+typedef struct sdebug_dev_info {
+ Scsi_Device * sdp;
+ unsigned short host_no;
+ unsigned short id;
+ char reset;
+ char sb_index;
+} Sdebug_dev_info;
+static Sdebug_dev_info * devInfop;
+
+static int num_aborts = 0;
+static int num_dev_resets = 0;
+static int num_bus_resets = 0;
+static int num_host_resets = 0;
-#ifdef SPEEDY
-#define VERIFY1_DEBUG(RW)
-#define VERIFY_DEBUG(RW)
-#else
+static spinlock_t mailbox_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t sdebug_atomic_rw = RW_LOCK_UNLOCKED;
-#define VERIFY1_DEBUG(RW) \
- if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
- start = 0; \
- if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
- if (bh){ \
- if (bh->b_size != 1024) panic ("Wrong bh size"); \
- if ((bh->b_blocknr << 1) + start != block) \
- { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \
- panic ("Wrong bh block#"); \
- }; \
- if (bh->b_dev != SCpnt->request.rq_dev) \
- panic ("Bad bh target"); \
- };
-
-#define VERIFY_DEBUG(RW) \
- if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \
- start = 0; \
- if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition"); \
- if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
- if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \
- if (SCpnt->request.sector + start != block) panic("Wrong block."); \
- if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \
- if (SCpnt->request.bh){ \
- if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
- if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \
- { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \
- panic ("Wrong bh block#"); \
- }; \
- if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \
- panic ("Bad bh target");\
- };
-#endif
+#include "scsi_debug.h"
typedef void (*done_fct_t) (Scsi_Cmnd *);
-static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] =
-{NULL,};
+static volatile done_fct_t * do_done = 0;
struct Scsi_Host * SHpnt = NULL;
+static int scsi_debug_read(Scsi_Cmnd * SCpnt, int upper_blk, int block,
+ int num, int * errstsp, Sdebug_dev_info * devip);
+static int scsi_debug_write(Scsi_Cmnd * SCpnt, int upper_blk, int block,
+ int num, int * errstsp, Sdebug_dev_info * devip);
static void scsi_debug_send_self_command(struct Scsi_Host * shpnt);
static void scsi_debug_intr_handle(unsigned long);
+static Sdebug_dev_info * devInfoReg(Scsi_Device * sdp);
+static void mk_sense_buffer(Sdebug_dev_info * devip, int index, int key,
+ int asc, int asq, int inbandLen);
+static int check_reset(Scsi_Cmnd * SCpnt, Sdebug_dev_info * devip);
-static struct timer_list timeout[SCSI_DEBUG_MAILBOXES];
-
-Scsi_Cmnd *SCint[SCSI_DEBUG_MAILBOXES] =
-{NULL,};
-static char SCrst[SCSI_DEBUG_MAILBOXES] =
-{0,};
+static struct timer_list * timeout = 0;
+static Scsi_Cmnd ** SCint = 0;
/*
* Semaphore used to simulate bus lockups.
*/
static int scsi_debug_lockup = 0;
-static char sense_buffer[128] =
-{0,};
+#define NUM_SENSE_BUFFS 4
+#define SENSE_BUFF_LEN 32
+static char sense_buffers[NUM_SENSE_BUFFS][SENSE_BUFF_LEN];
-static void scsi_dump(Scsi_Cmnd * SCpnt, int flag)
+static int made_block0 = 0;
+
+static void scsi_debug_mkblock0(unsigned char * buff, int bufflen,
+ Scsi_Cmnd * SCpnt)
{
int i;
-#if 0
- unsigned char *pnt;
-#endif
- unsigned int *lpnt;
- struct scatterlist *sgpnt = NULL;
- printk("use_sg: %d", SCpnt->use_sg);
- if (SCpnt->use_sg) {
- sgpnt = (struct scatterlist *) SCpnt->buffer;
- for (i = 0; i < SCpnt->use_sg; i++) {
- printk(":%p %d\n", sgpnt[i].address, sgpnt[i].length);
- };
- } else {
- printk("nosg: %p %p %d\n", SCpnt->request.buffer, SCpnt->buffer,
- SCpnt->bufflen);
- lpnt = (int *) SCpnt->request.buffer;
- if (lpnt)
- printk(" (Alt %x) ", lpnt[15]);
- };
- lpnt = (unsigned int *) SCpnt;
- for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) {
- if ((i & 7) == 0)
- printk("\n");
- printk("%x ", *lpnt++);
- };
- printk("\n");
- if (flag == 0)
- return;
-#if 0
- printk("\n");
- lpnt = (unsigned int *) sgpnt[0].address;
- for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) {
- if ((i & 7) == 0)
- printk("\n");
- printk("%x ", *lpnt++);
- };
- printk("\n");
-#endif
+ struct partition *p;
+
+ memset(buff, 0, bufflen);
+ *((unsigned short *) (buff + 510)) = 0xAA55;
+ p = (struct partition *) (buff + 0x1be);
+ i = 0;
+ while (starts[i + 1]) {
+ int start_cyl, end_cyl;
+
+ start_cyl = starts[i] / N_HEAD / N_SECTOR;
+ end_cyl = (starts[i + 1] - 1) / N_HEAD / N_SECTOR;
+ p->boot_ind = 0;
+
+ p->head = (i == 0 ? 1 : 0);
+ p->sector = 1 | ((start_cyl >> 8) << 6);
+ p->cyl = (start_cyl & 0xff);
+
+ p->end_head = N_HEAD - 1;
+ p->end_sector = N_SECTOR | ((end_cyl >> 8) << 6);
+ p->end_cyl = (end_cyl & 0xff);
+
+ p->start_sect = starts[i];
+ p->nr_sects = starts[i + 1] - starts[i];
+ p->sys_ind = 0x83; /* Linux ext2 partition */
+ p++;
+ i++;
+ }
+ if (!npart)
+ npart = i;
+ made_block0 = 1;
+ i = (bufflen > STORE_ELEM_SIZE) ? STORE_ELEM_SIZE : bufflen;
+ memcpy(store_arr[0].p, buff, i);
}
int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{
unchar *cmd = (unchar *) SCpnt->cmnd;
- struct partition *p;
int block;
- struct buffer_head *bh = NULL;
+ int upper_blk;
unsigned char *buff;
- int nbytes, sgcount;
int scsi_debug_errsts;
- struct scatterlist *sgpnt;
int target = SCpnt->target;
int bufflen = SCpnt->request_bufflen;
- unsigned long flags;
- int i;
- sgcount = 0;
- sgpnt = NULL;
-
-#ifdef CONFIG_SMP
- /*
- * The io_request_lock *must* be held at this point.
- */
- if( io_request_lock.lock == 0 )
- {
- printk("Warning - io_request_lock is not held in queuecommand\n");
- }
-#endif
+ unsigned long iflags;
+ int i, num, capac;
+ Sdebug_dev_info * devip = NULL;
+ char * sbuff;
/*
- * If we are being notified of the mid-level reposessing a command due to timeout,
- * just return.
+ * If we are being notified of the mid-level reposessing a command
+ * due to timeout, just return.
*/
if (done == NULL) {
return 0;
}
- DEB(if (target >= NR_FAKE_DISKS) {
- SCpnt->result = DID_TIME_OUT << 16; done(SCpnt); return 0;
- }
- );
buff = (unsigned char *) SCpnt->request_buffer;
@@ -229,249 +228,201 @@
* If a command comes for the ID of the host itself, just print
* a silly message and return.
*/
- if( target == 7 ) {
+ if(target == 7) {
printk("How do you do!\n");
SCpnt->result = 0;
done(SCpnt);
return 0;
}
- if (target >= NR_FAKE_DISKS || SCpnt->lun != 0) {
+ if ((target > 7) || (SCpnt->lun != 0)) {
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
}
- if (SCrst[target] != 0 && !scsi_debug_lockup) {
- SCrst[target] = 0;
- memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
- SCpnt->sense_buffer[0] = 0x70;
- SCpnt->sense_buffer[2] = UNIT_ATTENTION;
- SCpnt->result = (CHECK_CONDITION << 1);
- done(SCpnt);
+#if 0
+ printk(KERN_INFO "sdebug:qc: host_no=%d, id=%d, sdp=%p, cmd=0x%x\n",
+ (int)SCpnt->device->host->host_no, (int)SCpnt->device->id,
+ SCpnt->device, (int)(unsigned char)*cmd);
+#endif
+ if (NULL == SCpnt->device->hostdata) {
+ devip = devInfoReg(SCpnt->device);
+ if (NULL == devip) {
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
+ }
+ SCpnt->device->hostdata = devip;
}
+ devip = SCpnt->device->hostdata;
+
switch (*cmd) {
- case REQUEST_SENSE:
+ case REQUEST_SENSE: /* mandatory */
SCSI_LOG_LLQUEUE(3, printk("Request sense...\n"));
-#ifndef DEBUG
- {
- int i;
- printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt, buff, done, bufflen);
- for (i = 0; i < 12; i++)
- printk("%d ", sense_buffer[i]);
- printk("\n");
- };
-#endif
- memset(buff, 0, bufflen);
- memcpy(buff, sense_buffer, bufflen);
- memset(sense_buffer, 0, sizeof(sense_buffer));
+ if (devip) {
+ sbuff = &sense_buffers[(int)devip->sb_index][0];
+ devip->sb_index = 0;
+ }
+ else
+ sbuff = &sense_buffers[0][0];
+ memcpy(buff, sbuff, (bufflen < SENSE_BUFF_LEN) ?
+ bufflen : SENSE_BUFF_LEN);
+ memset(sbuff, 0, SENSE_BUFF_LEN);
+ sbuff[0] = 0x70;
SCpnt->result = 0;
done(SCpnt);
return 0;
case START_STOP:
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
SCSI_LOG_LLQUEUE(3, printk("START_STOP\n"));
scsi_debug_errsts = 0;
break;
case ALLOW_MEDIUM_REMOVAL:
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
if (cmd[4]) {
- SCSI_LOG_LLQUEUE(2, printk("Medium removal inhibited..."));
+ SCSI_LOG_LLQUEUE(2, printk(
+ "Medium removal inhibited..."));
} else {
- SCSI_LOG_LLQUEUE(2, printk("Medium removal enabled..."));
+ SCSI_LOG_LLQUEUE(2,
+ printk("Medium removal enabled..."));
}
scsi_debug_errsts = 0;
break;
- case INQUIRY:
+ case INQUIRY: /* mandatory */
SCSI_LOG_LLQUEUE(3, printk("Inquiry...(%p %d)\n", buff, bufflen));
memset(buff, 0, bufflen);
buff[0] = DEVICE_TYPE(target);
- buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */
- buff[2] = 1;
- buff[4] = 33 - 5;
- memcpy(&buff[8], "Foo Inc", 7);
- memcpy(&buff[16], "XYZZY", 5);
- memcpy(&buff[32], "1", 1);
+ buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0;
+ /* Removable disk */
+ buff[2] = 2; /* claim SCSI 2 */
+ buff[4] = 36 - 5;
+ memcpy(&buff[8], "Linux ", 8);
+ memcpy(&buff[16], "scsi_debug ", 16);
+ memcpy(&buff[32], "0002", 4);
+ scsi_debug_errsts = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
+ if (SCpnt->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
+ SCpnt->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
+#endif
+ break;
+ case SEND_DIAGNOSTIC: /* mandatory */
+ SCSI_LOG_LLQUEUE(3, printk("Send Diagnostic\n"));
+ if (buff)
+ memset(buff, 0, bufflen);
scsi_debug_errsts = 0;
break;
- case TEST_UNIT_READY:
+ case TEST_UNIT_READY: /* mandatory */
SCSI_LOG_LLQUEUE(3, printk("Test unit ready(%p %d)\n", buff, bufflen));
if (buff)
memset(buff, 0, bufflen);
scsi_debug_errsts = 0;
break;
case READ_CAPACITY:
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
SCSI_LOG_LLQUEUE(3, printk("Read Capacity\n"));
SHpnt = SCpnt->host;
- if (NR_REAL < 0)
- NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;
memset(buff, 0, bufflen);
- buff[0] = (CAPACITY >> 24);
- buff[1] = (CAPACITY >> 16) & 0xff;
- buff[2] = (CAPACITY >> 8) & 0xff;
- buff[3] = CAPACITY & 0xff;
+ capac = CAPACITY - 1;
+ buff[0] = (capac >> 24);
+ buff[1] = (capac >> 16) & 0xff;
+ buff[2] = (capac >> 8) & 0xff;
+ buff[3] = capac & 0xff;
buff[4] = 0;
buff[5] = 0;
- buff[6] = (SIZE(target) >> 8) & 0xff; /* 512 byte sectors */
- buff[7] = SIZE(target) & 0xff;
+ buff[6] = (SECT_SIZE_PER(target) >> 8) & 0xff;
+ buff[7] = SECT_SIZE_PER(target) & 0xff;
scsi_debug_errsts = 0;
break;
+ case SCSI_CMD_READ_16: /* SBC-2 */
+ case READ_12:
case READ_10:
case READ_6:
-#ifdef DEBUG
- printk("Read...");
-#endif
- if ((*cmd) == READ_10)
- block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
- else
- block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
- VERIFY_DEBUG(READ);
-#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
- {
- int delay = SCSI_SETUP_LATENCY;
-
- delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
- if (delay)
- usleep(delay);
- };
-#endif
-
-#ifdef DEBUG
- printk("(r%d)", SCpnt->request.nr_sectors);
-#endif
- nbytes = bufflen;
- if (SCpnt->use_sg) {
- sgcount = 0;
- sgpnt = (struct scatterlist *) buff;
- buff = sgpnt[sgcount].address;
- bufflen = sgpnt[sgcount].length;
- bh = SCpnt->request.bh;
- };
- scsi_debug_errsts = 0;
- do {
- VERIFY1_DEBUG(READ);
- /* For the speedy test, we do not even want to fill the buffer with anything */
-#ifdef CLEAR
- memset(buff, 0, bufflen);
-#endif
- /* If this is block 0, then we want to read the partition table for this
- * device. Let's make one up */
- if (block == 0) {
- int i;
- memset(buff, 0, bufflen);
- *((unsigned short *) (buff + 510)) = 0xAA55;
- p = (struct partition *) (buff + 0x1be);
- i = 0;
- while (starts[i + 1]) {
- int start_cyl, end_cyl;
-
- start_cyl = starts[i] / N_HEAD / N_SECTOR;
- end_cyl = (starts[i + 1] - 1) / N_HEAD / N_SECTOR;
- p->boot_ind = 0;
-
- p->head = (i == 0 ? 1 : 0);
- p->sector = 1 | ((start_cyl >> 8) << 6);
- p->cyl = (start_cyl & 0xff);
-
- p->end_head = N_HEAD - 1;
- p->end_sector = N_SECTOR | ((end_cyl >> 8) << 6);
- p->end_cyl = (end_cyl & 0xff);
-
- p->start_sect = starts[i];
- p->nr_sects = starts[i + 1] - starts[i];
- p->sys_ind = 0x81; /* Linux partition */
- p++;
- i++;
- };
- if (!npart)
- npart = i;
- scsi_debug_errsts = 0;
- break;
- };
-#ifdef DEBUG
- if (SCpnt->use_sg)
- printk("Block %x (%d %d)\n", block, SCpnt->request.nr_sectors,
- SCpnt->request.current_nr_sectors);
-#endif
-
-#if 0
- /* Simulate a disk change */
- if (block == 0xfff0) {
- sense_buffer[0] = 0x70;
- sense_buffer[2] = UNIT_ATTENTION;
- starts[0] += 10;
- starts[1] += 10;
- starts[2] += 10;
-
-#ifdef DEBUG
- {
- int i;
- printk("scsi_debug: Filling sense buffer:");
- for (i = 0; i < 12; i++)
- printk("%d ", sense_buffer[i]);
- printk("\n");
- };
-#endif
- scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
- break;
- } /* End phony disk change code */
-#endif
-
-#ifdef CLEAR
- memcpy(buff, &target, sizeof(target));
- memcpy(buff + sizeof(target), cmd, 24);
- memcpy(buff + 60, &block, sizeof(block));
- memcpy(buff + 64, SCpnt, sizeof(Scsi_Cmnd));
-#endif
- nbytes -= bufflen;
- if (SCpnt->use_sg) {
-#ifdef CLEAR
- memcpy(buff + 128, bh, sizeof(struct buffer_head));
-#endif
- block += bufflen >> 9;
- bh = bh->b_reqnext;
- sgcount++;
- if (nbytes) {
- if (!bh)
- panic("Too few blocks for linked request.");
- buff = sgpnt[sgcount].address;
- bufflen = sgpnt[sgcount].length;
- };
- }
- } while (nbytes);
-
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
+ upper_blk = 0;
+ if ((*cmd) == SCSI_CMD_READ_16) {
+ upper_blk = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ block = cmd[9] + (cmd[8] << 8) +
+ (cmd[7] << 16) + (cmd[6] << 24);
+ num = cmd[13] + (cmd[12] << 8) +
+ (cmd[11] << 16) + (cmd[10] << 24);
+ }
+ else if ((*cmd) == READ_12) {
+ block = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ num = cmd[9] + (cmd[8] << 8) +
+ (cmd[7] << 16) + (cmd[6] << 24);
+ }
+ else if ((*cmd) == READ_10) {
+ block = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ num = cmd[8] + (cmd[7] << 8);
+ }
+ else {
+ block = cmd[3] + (cmd[2] << 8) +
+ ((cmd[1] & 0x1f) << 16);
+ num = cmd[4];
+ }
+ if (scsi_debug_read(SCpnt, upper_blk, block, num,
+ &scsi_debug_errsts, devip))
+ break;
SCpnt->result = 0;
- (done) (SCpnt);
+/* calls bottom half in upper layers before return from scsi_do_...() */
+ (done) (SCpnt);
return 0;
-
- if (SCpnt->use_sg && !scsi_debug_errsts)
- if (bh)
- scsi_dump(SCpnt, 0);
- break;
+ case SCSI_CMD_WRITE_16: /* SBC-2 */
+ case WRITE_12:
case WRITE_10:
case WRITE_6:
-#ifdef DEBUG
- printk("Write\n");
-#endif
- if ((*cmd) == WRITE_10)
- block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
- else
- block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
- VERIFY_DEBUG(WRITE);
- /* printk("(w%d)",SCpnt->request.nr_sectors); */
- if (SCpnt->use_sg) {
- if ((bufflen >> 9) != SCpnt->request.nr_sectors)
- panic("Trying to write wrong number of blocks\n");
- sgpnt = (struct scatterlist *) buff;
- buff = sgpnt[sgcount].address;
- };
-#if 0
- if (block != *((unsigned long *) (buff + 60))) {
- printk("%x %x :", block, *((unsigned long *) (buff + 60)));
- scsi_dump(SCpnt, 1);
- panic("Bad block written.\n");
- };
-#endif
- scsi_debug_errsts = 0;
- break;
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
+ upper_blk = 0;
+ if ((*cmd) == SCSI_CMD_WRITE_16) {
+ upper_blk = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ block = cmd[9] + (cmd[8] << 8) +
+ (cmd[7] << 16) + (cmd[6] << 24);
+ num = cmd[13] + (cmd[12] << 8) +
+ (cmd[11] << 16) + (cmd[10] << 24);
+ }
+ else if ((*cmd) == WRITE_12) {
+ block = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ num = cmd[9] + (cmd[8] << 8) +
+ (cmd[7] << 16) + (cmd[6] << 24);
+ }
+ else if ((*cmd) == WRITE_10) {
+ block = cmd[5] + (cmd[4] << 8) +
+ (cmd[3] << 16) + (cmd[2] << 24);
+ num = cmd[8] + (cmd[7] << 8);
+ }
+ else {
+ block = cmd[3] + (cmd[2] << 8) +
+ ((cmd[1] & 0x1f) << 16);
+ num = cmd[4];
+ }
+ if (scsi_debug_write(SCpnt, upper_blk, block, num,
+ &scsi_debug_errsts, devip))
+ break;
+ SCpnt->result = 0;
+/* calls bottom half in upper layers before return from scsi_do_...() */
+ (done) (SCpnt);
+ return 0;
case MODE_SENSE:
/*
* Used to detect write protected status.
@@ -480,26 +431,36 @@
memset(buff, 0, 6);
break;
default:
+#if 0
SCSI_LOG_LLQUEUE(3, printk("Unknown command %d\n", *cmd));
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
- };
+#else
+ if (check_reset(SCpnt, devip)) {
+ done(SCpnt);
+ return 0;
+ }
+ scsi_debug_errsts = (COMMAND_COMPLETE << 8) |
+ (CHECK_CONDITION << 1);
+ mk_sense_buffer(devip, 2, ILLEGAL_REQUEST, 0x20, 0, 14);
+ break;
+#endif
+ }
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&mailbox_lock, iflags);
for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) {
if (timeout[i].function == NULL)
break;
- };
+ }
/*
- * If all of the slots are full, just return 1. The new error handling scheme
- * allows this, and the mid-level should queue things.
+ * If all of the slots are full, just return 1. The new error
+ * handling scheme allows this, and the mid-level should queue things.
*/
if (i >= SCSI_DEBUG_MAILBOXES || timeout[i].function != 0) {
SCSI_LOG_LLQUEUE(1, printk("Command rejected - host busy\n"));
- restore_flags(flags);
+ spin_unlock_irqrestore(&mailbox_lock, iflags);
return 1;
}
SCSI_LOG_LLQUEUE(1, printk("Command accepted - slot %d\n", i));
@@ -511,7 +472,7 @@
do_done[i] = done;
scsi_debug_intr_handle(i); /* No timer - do this one right away */
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&mailbox_lock, iflags);
#else
SCpnt->result = scsi_debug_errsts;
@@ -521,19 +482,200 @@
SCint[i] = SCpnt;
do_done[i] = done;
- restore_flags(flags);
+ spin_unlock_irqrestore(&mailbox_lock, iflags);
add_timer(&timeout[i]);
if (!done)
- panic("scsi_debug_queuecommand: done can't be NULL\n");
+ printk("scsi_debug_queuecommand: done can't be NULL\n");
#if 0
- printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires, jiffies);
+ printk("Sending command (%d %x %d %d)...", i, done,
+ timeout[i].expires, jiffies);
#endif
#endif
return 0;
}
+static int check_reset(Scsi_Cmnd * SCpnt, Sdebug_dev_info * devip)
+{
+ if (devip->reset) {
+ devip->reset = 0;
+ mk_sense_buffer(devip, 3, UNIT_ATTENTION, 0x29, 0, 14);
+ SCpnt->result = (COMMAND_COMPLETE << 8) |
+ (CHECK_CONDITION << 1);
+ return 1;
+ }
+ return 0;
+}
+
+static inline
+unsigned char * sdebug_scatg2virt(const struct scatterlist * sclp)
+{
+ if (NULL == sclp)
+ return NULL;
+ else if (sclp->page)
+ return (unsigned char *)page_address(sclp->page) +
+ sclp->offset;
+ else {
+#ifdef SDEBUG_SG_ADDRESS
+ return sclp->address;
+#else
+ return NULL;
+#endif
+ }
+}
+
+static int scsi_debug_read(Scsi_Cmnd * SCpnt, int upper_blk, int block,
+ int num, int * errstsp, Sdebug_dev_info * devip)
+{
+ unsigned char *buff = (unsigned char *) SCpnt->request_buffer;
+ int nbytes, sgcount;
+ struct scatterlist *sgpnt = NULL;
+ int bufflen = SCpnt->request_bufflen;
+ unsigned long iflags;
+
+ if (upper_blk || (block + num > CAPACITY)) {
+ *errstsp = (COMMAND_COMPLETE << 8) |
+ (CHECK_CONDITION << 1);
+ mk_sense_buffer(devip, 1, ILLEGAL_REQUEST, 0x21, 0, 14);
+ return 1;
+ }
+#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
+ {
+ int delay = SCSI_SETUP_LATENCY;
+
+ delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
+ if (delay)
+ usleep(delay);
+ }
+#endif
+
+ read_lock_irqsave(&sdebug_atomic_rw, iflags);
+ sgcount = 0;
+ nbytes = bufflen;
+ /* printk("scsi_debug_read: block=%d, tot_bufflen=%d\n",
+ block, bufflen); */
+ if (SCpnt->use_sg) {
+ sgcount = 0;
+ sgpnt = (struct scatterlist *) buff;
+ buff = sdebug_scatg2virt(&sgpnt[sgcount]);
+ bufflen = sgpnt[sgcount].length;
+ }
+ *errstsp = 0;
+ do {
+ int resid, k, off, len, rem, blk;
+ unsigned char * bp;
+
+ /* If this is block 0, then we want to read the partition
+ * table for this device. Let's make one up */
+ if (scsi_debug_fake_blk0 && (block == 0) && (! made_block0)) {
+ scsi_debug_mkblock0(buff, bufflen, SCpnt);
+ *errstsp = 0;
+ break;
+ }
+ bp = buff;
+ blk = block;
+ for (resid = bufflen; resid > 0; resid -= len) {
+ k = blk / SECT_PER_ELEM;
+ off = (blk % SECT_PER_ELEM) * SECT_SIZE;
+ rem = STORE_ELEM_SIZE - off;
+ len = (resid > rem) ? rem : resid;
+/* printk("sdr: blk=%d k=%d off=%d rem=%d resid"
+ "=%d len=%d sgcount=%d\n", blk, k,
+ off, rem, resid, len, sgcount); */
+ memcpy(bp, store_arr[k].p + off, len);
+ bp += len;
+ blk += len / SECT_SIZE;
+ }
+#if 0
+ /* Simulate a disk change */
+ if (block == 0xfff0) {
+ sense_buffer[0] = 0x70;
+ sense_buffer[2] = UNIT_ATTENTION;
+ starts[0] += 10;
+ starts[1] += 10;
+ starts[2] += 10;
+
+ *errstsp = (COMMAND_COMPLETE << 8) |
+ (CHECK_CONDITION << 1);
+ read_unlock_irqrestore(&sdebug_atomic_rw, iflags);
+ return 1;
+ } /* End phony disk change code */
+#endif
+ nbytes -= bufflen;
+ if (SCpnt->use_sg) {
+ block += bufflen >> POW2_SECT_SIZE;
+ sgcount++;
+ if (nbytes) {
+ buff = sdebug_scatg2virt(&sgpnt[sgcount]);
+ bufflen = sgpnt[sgcount].length;
+ }
+ }
+ else if (nbytes > 0)
+ printk("sdebug_read: unexpected nbytes=%d\n", nbytes);
+ } while (nbytes);
+ read_unlock_irqrestore(&sdebug_atomic_rw, iflags);
+ return 0;
+}
+
+static int scsi_debug_write(Scsi_Cmnd * SCpnt, int upper_blk, int block,
+ int num, int * errstsp, Sdebug_dev_info * devip)
+{
+ unsigned char *buff = (unsigned char *) SCpnt->request_buffer;
+ int nbytes, sgcount;
+ struct scatterlist *sgpnt = NULL;
+ int bufflen = SCpnt->request_bufflen;
+ unsigned long iflags;
+
+ if (upper_blk || (block + num > CAPACITY)) {
+ *errstsp = (COMMAND_COMPLETE << 8) |
+ (CHECK_CONDITION << 1);
+ mk_sense_buffer(devip, 1, ILLEGAL_REQUEST, 0x21, 0, 14);
+ return 1;
+ }
+
+ write_lock_irqsave(&sdebug_atomic_rw, iflags);
+ sgcount = 0;
+ nbytes = bufflen;
+ if (SCpnt->use_sg) {
+ sgcount = 0;
+ sgpnt = (struct scatterlist *) buff;
+ buff = sdebug_scatg2virt(&sgpnt[sgcount]);
+ bufflen = sgpnt[sgcount].length;
+ }
+ *errstsp = 0;
+ do {
+ int resid, k, off, len, rem, blk;
+ unsigned char * bp;
+
+ bp = buff;
+ blk = block;
+ for (resid = bufflen; resid > 0; resid -= len) {
+ k = blk / SECT_PER_ELEM;
+ off = (blk % SECT_PER_ELEM) * SECT_SIZE;
+ rem = STORE_ELEM_SIZE - off;
+ len = (resid > rem) ? rem : resid;
+ memcpy(store_arr[k].p + off, bp, len);
+ bp += len;
+ blk += len / SECT_SIZE;
+ }
+
+ nbytes -= bufflen;
+ if (SCpnt->use_sg) {
+ block += bufflen >> POW2_SECT_SIZE;
+ sgcount++;
+ if (nbytes) {
+ buff = sdebug_scatg2virt(&sgpnt[sgcount]);
+ bufflen = sgpnt[sgcount].length;
+ }
+ }
+ else if (nbytes > 0)
+ printk("sdebug_write: unexpected nbytes=%d\n", nbytes);
+ } while (nbytes);
+ write_unlock_irqrestore(&sdebug_atomic_rw, iflags);
+ return 0;
+}
+
static void scsi_debug_send_self_command(struct Scsi_Host * shpnt)
{
static unsigned char cmd[6] =
@@ -581,10 +723,6 @@
{
Scsi_Cmnd *SCtmp;
void (*my_done) (Scsi_Cmnd *);
-#ifdef DEBUG
- int to;
-#endif
-
#if 0
del_timer(&timeout[indx]);
#endif
@@ -599,59 +737,219 @@
printk("scsi_debug_intr_handle: Unexpected interrupt\n");
return;
}
-#ifdef DEBUG
+#if 0
printk("In intr_handle...");
printk("...done %d %x %d %d\n", i, my_done, to, jiffies);
printk("In intr_handle: %d %x %x\n", i, SCtmp, my_done);
#endif
my_done(SCtmp);
-#ifdef DEBUG
+#if 0
printk("Called done.\n");
#endif
}
+static int initialized = 0;
+
+static int do_init(void)
+{
+ int sz;
+
+ starts[3] = CAPACITY;
+ sz = sizeof(Sd_store_elem) * STORE_ELEMENTS;
+ store_arr = kmalloc(sz, GFP_ATOMIC);
+ if (NULL == store_arr)
+ return 1;
+ memset(store_arr, 0, sz);
+
+ sz = sizeof(done_fct_t) * SCSI_DEBUG_MAILBOXES;
+ do_done = kmalloc(sz, GFP_ATOMIC);
+ if (NULL == do_done)
+ goto out;
+ memset((void *)do_done, 0, sz);
+
+ sz = sizeof(struct timer_list) * SCSI_DEBUG_MAILBOXES;
+ timeout = kmalloc(sz, GFP_ATOMIC);
+ if (NULL == timeout)
+ goto out;
+ memset(timeout, 0, sz);
+
+ sz = sizeof(Scsi_Cmnd *) * SCSI_DEBUG_MAILBOXES;
+ SCint = kmalloc(sz, GFP_ATOMIC);
+ if (NULL == SCint)
+ goto out;
+ memset(SCint, 0, sz);
+
+ return 0;
+
+out:
+ if (store_arr)
+ kfree(store_arr);
+ if (do_done)
+ kfree((void *)do_done);
+ if (timeout)
+ kfree(timeout);
+ if (SCint)
+ kfree(SCint);
+ return 1;
+}
+
+static void do_end(void)
+{
+ kfree(SCint);
+ kfree(timeout);
+ kfree((void *)do_done);
+ kfree(store_arr);
+}
+
int scsi_debug_detect(Scsi_Host_Template * tpnt)
{
- int i;
+ int k, num, sz;
+
+ if (0 == initialized) {
+ ++initialized;
+ sz = sizeof(Sdebug_dev_info) * scsi_debug_num_devs;
+ devInfop = kmalloc(sz, GFP_ATOMIC);
+ if (NULL == devInfop) {
+ printk("scsi_debug_detect: out of memory, 0.5\n");
+ return 0;
+ }
+ memset(devInfop, 0, sz);
+ if (do_init()) {
+ printk("scsi_debug_detect: out of memory, 0\n");
+ return 0;
+ }
+ for (k = 0; k < STORE_ELEMENTS; ++k) {
+ store_arr[k].p = (unsigned char *)
+ __get_free_pages(GFP_ATOMIC, STORE_ELEM_ORDER);
+ if (0 == store_arr[k].p)
+ goto detect_err;
+ memset(store_arr[k].p, 0, STORE_ELEM_SIZE);
+ }
+ for (k = 0; k < NUM_SENSE_BUFFS; ++k)
+ sense_buffers[k][0] = 0x70;
+ for (k = 0; k < NR_HOSTS_PRESENT; k++) {
+ tpnt->proc_name = "scsi_debug"; /* In the loop??? */
+ scsi_register(tpnt, 0);
+ }
+ return NR_HOSTS_PRESENT;
+ }
+ else {
+ printk("scsi_debug_detect: called again\n");
+ return 0;
+ }
- for (i = 0; i < NR_HOSTS_PRESENT; i++) {
- tpnt->proc_name = "scsi_debug"; /* Huh? In the loop??? */
- scsi_register(tpnt, 0);
+detect_err:
+ num = k;
+ for (k = 0; k < STORE_ELEMENTS; ++k) {
+ if (0 != store_arr[k].p) {
+ free_pages((unsigned long)store_arr[k].p,
+ STORE_ELEM_ORDER);
+ store_arr[k].p = NULL;
+ }
}
- return NR_HOSTS_PRESENT;
+ printk("scsi_debug_detect: out of memory: %d out of %d bytes\n",
+ (int)(num * STORE_ELEM_SIZE),
+ (int)(scsi_debug_dev_size_mb * 1024 * 1024));
+ return 0;
+}
+
+
+static int num_releases = 0;
+
+int scsi_debug_release(struct Scsi_Host * hpnt)
+{
+ int k;
+
+ scsi_unregister(hpnt);
+ if (++num_releases != NR_HOSTS_PRESENT)
+ return 0;
+
+ for (k = 0; k < STORE_ELEMENTS; ++k) {
+ if (0 != store_arr[k].p) {
+ free_pages((unsigned long)store_arr[k].p,
+ STORE_ELEM_ORDER);
+ store_arr[k].p = NULL;
+ }
+ }
+ do_end();
+ kfree(devInfop);
+ return 0;
+}
+
+static Sdebug_dev_info * devInfoReg(Scsi_Device * sdp)
+{
+ int k;
+ unsigned short host_no, id;
+ Sdebug_dev_info * devip;
+
+ host_no = sdp->host->host_no;
+ id = (unsigned short)sdp->id;
+ for (k = 0; k < scsi_debug_num_devs; ++k) {
+ devip = &devInfop[k];
+ if (devip->sdp && (host_no == devip->host_no) &&
+ (id == devip->id)) {
+ devip->sdp = sdp; /* overwrite previous sdp */
+ return devip;
+ }
+ if (NULL == devip->sdp) {
+ devip->sdp = sdp;
+ devip->host_no = host_no;
+ devip->id = id;
+ devip->reset = 1;
+ devip->sb_index = 0;
+ return devip;
+ }
+ }
+ return NULL;
+}
+
+static void mk_sense_buffer(Sdebug_dev_info * devip, int index, int key,
+ int asc, int asq, int inbandLen)
+{
+ char * sbuff;
+ if ((index < 0) || (index >= NUM_SENSE_BUFFS))
+ return;
+ if (devip)
+ devip->sb_index = index;
+ sbuff = &sense_buffers[index][0];
+ memset(sbuff, 0, SENSE_BUFF_LEN);
+ sbuff[0] = 0x70;
+ sbuff[2] = key;
+ sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0;
+ sbuff[12] = asc;
+ sbuff[13] = asq;
}
int scsi_debug_abort(Scsi_Cmnd * SCpnt)
{
-#if 0
+#if 1
+ ++num_aborts;
+ return SUCCESS;
+#else
int j;
void (*my_done) (Scsi_Cmnd *);
- unsigned long flags;
-#endif
-
- DEB(printk("scsi_debug_abort\n"));
-#if 0
+ unsigned long iflags;
SCpnt->result = SCpnt->abort_reason << 16;
for (j = 0; j < SCSI_DEBUG_MAILBOXES; j++) {
if (SCpnt == SCint[j]) {
my_done = do_done[j];
my_done(SCpnt);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&mailbox_lock, iflags);
timeout[j] = 0;
SCint[j] = NULL;
do_done[j] = NULL;
- restore_flags(flags);
- };
- };
-#endif
+ spin_unlock_irqrestore(&mailbox_lock, iflags);
+ }
+ }
return SCSI_ABORT_SNOOZE;
+#endif
}
int scsi_debug_biosparam(Disk * disk, kdev_t dev, int *info)
{
+ /* int size = disk->capacity; */
info[0] = N_HEAD;
info[1] = N_SECTOR;
info[2] = N_CYLINDER;
@@ -660,35 +958,130 @@
return 0;
}
+#if 0
int scsi_debug_reset(Scsi_Cmnd * SCpnt, unsigned int why)
{
int i;
- unsigned long flags;
+ unsigned long iflags;
void (*my_done) (Scsi_Cmnd *);
printk("Bus unlocked by reset - %d\n", why);
scsi_debug_lockup = 0;
- DEB(printk("scsi_debug_reset called\n"));
for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) {
if (SCint[i] == NULL)
continue;
SCint[i]->result = DID_RESET << 16;
my_done = do_done[i];
my_done(SCint[i]);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&mailbox_lock, iflags);
SCint[i] = NULL;
do_done[i] = NULL;
timeout[i].function = NULL;
- restore_flags(flags);
+ spin_unlock_irqrestore(&mailbox_lock, iflags);
}
return SCSI_RESET_SUCCESS;
}
+#endif
+
+int scsi_debug_device_reset(Scsi_Cmnd * SCpnt)
+{
+ Scsi_Device * sdp;
+ int k;
+
+ ++num_dev_resets;
+ if (SCpnt && ((sdp = SCpnt->device))) {
+ for (k = 0; k < scsi_debug_num_devs; ++k) {
+ if (sdp->hostdata == (devInfop + k))
+ break;
+ }
+ if (k < scsi_debug_num_devs)
+ devInfop[k].reset = 1;
+ }
+ return SUCCESS;
+}
-const char *scsi_debug_info(void)
+int scsi_debug_bus_reset(Scsi_Cmnd * SCpnt)
{
- static char buffer[] = " "; /* looks nicer without anything here */
- return buffer;
+ Scsi_Device * sdp;
+ struct Scsi_Host * hp;
+ int k;
+
+ ++num_bus_resets;
+ if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+ for (k = 0; k < scsi_debug_num_devs; ++k) {
+ if (hp == devInfop[k].sdp->host)
+ devInfop[k].reset = 1;
+ }
+ }
+ return SUCCESS;
+}
+
+int scsi_debug_host_reset(Scsi_Cmnd * SCpnt)
+{
+ int k;
+
+ ++num_host_resets;
+ for (k = 0; k < scsi_debug_num_devs; ++k)
+ devInfop[k].reset = 1;
+
+ return SUCCESS;
+}
+
+#ifndef MODULE
+static int __init scsi_debug_num_devs_setup(char *str)
+{
+ int tmp;
+
+ if (get_option(&str, &tmp) == 1) {
+ if (tmp > 0)
+ scsi_debug_num_devs = tmp;
+ return 1;
+ } else {
+ printk("scsi_debug_num_devs: usage scsi_debug_num_devs= "
+ "( can be from 1 to around 2000)\n");
+ return 0;
+ }
+}
+
+__setup("scsi_debug_num_devs=", scsi_debug_num_devs_setup);
+
+static int __init scsi_debug_dev_size_mb_setup(char *str)
+{
+ int tmp;
+
+ if (get_option(&str, &tmp) == 1) {
+ if (tmp > 0)
+ scsi_debug_dev_size_mb = tmp;
+ return 1;
+ } else {
+ printk("scsi_debug_dev_size_mb: usage scsi_debug_dev_size_mb=\n"
+ " ( is number of MB ram shared by all devs\n");
+ return 0;
+ }
+}
+
+__setup("scsi_debug_dev_size_mb=", scsi_debug_dev_size_mb_setup);
+#endif
+
+MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
+MODULE_DESCRIPTION("SCSI debug adapter driver");
+MODULE_PARM(scsi_debug_num_devs, "i");
+MODULE_PARM_DESC(scsi_debug_num_devs, "number of SCSI devices to simulate");
+MODULE_PARM(scsi_debug_dev_size_mb, "i");
+MODULE_PARM_DESC(scsi_debug_dev_size_mb, "size in MB of ram shared by devs");
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+static char sdebug_info[256];
+
+const char * scsi_debug_info(struct Scsi_Host * shp)
+{
+ sprintf(sdebug_info, "scsi_debug, %s, num_devs=%d, "
+ "dev_size_mb=%d\n", scsi_debug_version_str,
+ scsi_debug_num_devs, scsi_debug_dev_size_mb);
+ return sdebug_info;
}
/* scsi_debug_proc_info
@@ -738,10 +1131,20 @@
}
begin = 0;
- pos = len = sprintf(buffer,
- "This driver is not a real scsi driver, but it plays one on TV.\n"
+ pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n"
+ "num_devs=%d, shared (ram) size=%d MB, sector_size=%d bytes\n"
+ "cylinders=%d, heads=%d, sectors=%d\n"
+ "number of aborts=%d, device_reset=%d, bus_resets=%d, "
+ "host_resets=%d\n",
+ scsi_debug_version_str, scsi_debug_num_devs,
+ scsi_debug_dev_size_mb, SECT_SIZE,
+ N_CYLINDER, N_HEAD, N_SECTOR,
+ num_aborts, num_dev_resets, num_bus_resets, num_host_resets);
+#if 0
+ "This driver is not a real scsi driver, but it plays one on TV.\n"
"It is very handy for debugging specific problems because you\n"
"can simulate a variety of error conditions\n");
+#endif
if (pos < offset) {
len = 0;
begin = pos;
@@ -754,44 +1157,8 @@
return (len);
}
-#ifdef CONFIG_USER_DEBUG
-/*
- * This is a hack for the user space emulator. It allows us to
- * "insert" arbitrary numbers of additional drivers.
- */
-void *scsi_debug_get_handle(void)
-{
- static Scsi_Host_Template driver_copy = SCSI_DEBUG;
- void *rtn;
- rtn = kmalloc(sizeof(driver_copy), GFP_ATOMIC);
- if(rtn==NULL)
- return NULL;
- memcpy(rtn, (void *) &driver_copy, sizeof(driver_copy));
- return rtn;
-}
-#endif
-
/* Eventually this will go into an include file, but this will be later */
-static Scsi_Host_Template driver_template = SCSI_DEBUG;
+static Scsi_Host_Template driver_template = SCSI_DEBUG_TEMPLATE;
#include "scsi_module.c"
-/*
- * 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
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
-MODULE_LICENSE("GPL");
diff -u --recursive --new-file pre1/linux/drivers/scsi/scsi_debug.h linux/drivers/scsi/scsi_debug.h
--- pre1/linux/drivers/scsi/scsi_debug.h Wed Nov 28 10:22:27 2001
+++ linux/drivers/scsi/scsi_debug.h Thu Jan 17 13:59:33 2002
@@ -8,34 +8,41 @@
int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
int scsi_debug_abort(Scsi_Cmnd *);
int scsi_debug_biosparam(Disk *, kdev_t, int[]);
-int scsi_debug_reset(Scsi_Cmnd *, unsigned int);
+int scsi_debug_bus_reset(Scsi_Cmnd *);
+int scsi_debug_dev_reset(Scsi_Cmnd *);
+int scsi_debug_host_reset(Scsi_Cmnd *);
int scsi_debug_proc_info(char *, char **, off_t, int, int, int);
+const char * scsi_debug_info(struct Scsi_Host *);
#ifndef NULL
#define NULL 0
#endif
-
-#define SCSI_DEBUG_MAILBOXES 1
-
/*
- * Allow the driver to reject commands. Thus we accept only one, but
- * and the mid-level will queue the remainder.
+ * This driver is written for the lk 2.5 series
*/
#define SCSI_DEBUG_CANQUEUE 255
-#define SCSI_DEBUG {proc_info: scsi_debug_proc_info, \
+#define SCSI_DEBUG_MAX_CMD_LEN 16
+
+#define SCSI_DEBUG_TEMPLATE \
+ {proc_info: scsi_debug_proc_info, \
name: "SCSI DEBUG", \
+ info: scsi_debug_info, \
detect: scsi_debug_detect, \
+ release: scsi_debug_release, \
queuecommand: scsi_debug_queuecommand, \
- abort: scsi_debug_abort, \
- reset: scsi_debug_reset, \
+ eh_abort_handler: scsi_debug_abort, \
+ eh_bus_reset_handler: scsi_debug_bus_reset, \
+ eh_device_reset_handler: scsi_debug_device_reset, \
+ eh_host_reset_handler: scsi_debug_host_reset, \
bios_param: scsi_debug_biosparam, \
can_queue: SCSI_DEBUG_CANQUEUE, \
this_id: 7, \
- sg_tablesize: 16, \
+ sg_tablesize: 64, \
cmd_per_lun: 3, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
}
+
#endif
diff -u --recursive --new-file pre1/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- pre1/linux/drivers/scsi/sg.c Thu Jan 3 11:35:33 2002
+++ linux/drivers/scsi/sg.c Thu Jan 17 13:59:33 2002
@@ -19,9 +19,9 @@
*/
#include
#ifdef CONFIG_PROC_FS
- static char sg_version_str[] = "Version: 3.1.20 (20010814)";
+ static char sg_version_str[] = "Version: 3.5.23 (20020103)";
#endif
- static int sg_version_num = 30120; /* 2 digits for each component */
+ static int sg_version_num = 30523; /* 2 digits for each component */
/*
* D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
* - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
@@ -76,12 +76,18 @@
#include
#endif /* LINUX_VERSION_CODE */
+#define SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
+
#define SG_ALLOW_DIO_DEF 0
#define SG_ALLOW_DIO_CODE /* compile out be commenting this define */
#ifdef SG_ALLOW_DIO_CODE
#include
#endif
+#define SG_NEW_KIOVEC 0 /* use alloc_kiovec(), not alloc_kiovec_sz() */
+
+#define SG_MAX_DEVS_MASK ((1U << KDEV_MINOR_BITS) - 1)
+
int sg_big_buff = SG_DEF_RESERVED_SIZE;
/* N.B. This variable is readable and writeable via
/proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
@@ -95,14 +101,8 @@
#define SG_SECTOR_SZ 512
#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
-#define SG_LOW_POOL_THRESHHOLD 30
-#define SG_MAX_POOL_SECTORS 320 /* Max. number of pool sectors to take */
-
-static int sg_pool_secs_avail = SG_MAX_POOL_SECTORS;
-
#define SG_HEAP_PAGE 1 /* heap from kernel via get_free_pages() */
#define SG_HEAP_KMAL 2 /* heap from kernel via kmalloc() */
-#define SG_HEAP_POOL 3 /* heap from scsi dma pool (mid-level) */
#define SG_USER_MEM 4 /* memory belongs to user space */
#define SG_DEV_ARR_LUMP 6 /* amount to over allocate sg_dev_arr by */
@@ -136,10 +136,10 @@
typedef struct sg_scatter_hold /* holding area for scsi scatter gather info */
{
unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
- unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
unsigned bufflen; /* Size of (aggregate) data buffer */
unsigned b_malloc_len; /* actual len malloc'ed in buffer */
- void * buffer; /* Data buffer or scatter list,12 bytes each*/
+ void * buffer; /* Data buffer or scatter list + mem_src_arr */
struct kiobuf * kiobp; /* for direct IO information */
char mapped; /* indicates kiobp has locked pages */
char buffer_mem_src; /* heap whereabouts of 'buffer' */
@@ -182,6 +182,7 @@
char cmd_q; /* 1 -> allow command queuing, 0 -> don't */
char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
+ char mmap_called; /* 0 -> mmap() never called on this fd */
} Sg_fd; /* 2760 bytes long on i386 */
typedef struct sg_device /* holds the state of each scsi generic device */
@@ -203,7 +204,8 @@
static int sg_start_req(Sg_request * srp);
static void sg_finish_rem_req(Sg_request * srp);
static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
-static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp);
+static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
+ int tablesize);
static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,
Sg_request * srp);
static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count,
@@ -233,13 +235,15 @@
static Sg_request * sg_add_request(Sg_fd * sfp);
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
static int sg_res_in_use(Sg_fd * sfp);
-static void sg_clr_srpnt(Scsi_Request * SRpnt);
static int sg_ms_to_jif(unsigned int msecs);
-static unsigned sg_jif_to_ms(int jifs);
+static inline unsigned sg_jif_to_ms(int jifs);
static int sg_allow_access(unsigned char opcode, char dev_type);
static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
static void sg_unmap_and(Sg_scatter_hold * schp, int free_also);
static Sg_device * sg_get_dev(int dev);
+static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp);
+static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp);
+static inline unsigned char * sg_scatg2virt(const struct scatterlist * sclp);
#ifdef CONFIG_PROC_FS
static int sg_last_dev(void);
#endif
@@ -337,9 +341,8 @@
Sg_device * sdp;
Sg_fd * sfp;
- if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
return -ENXIO;
- }
SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", minor(sdp->i_rdev)));
sg_fasync(-1, filp, 0); /* remove filp from async notification list */
if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
@@ -615,6 +618,20 @@
sg_remove_request(sfp, srp);
return -ENOSYS;
}
+ if (hp->flags & SG_FLAG_MMAP_IO) {
+ if (hp->dxfer_len > sfp->reserve.bufflen) {
+ sg_remove_request(sfp, srp);
+ return -ENOMEM; /* MMAP_IO size must fit in reserve buffer */
+ }
+ if (hp->flags & SG_FLAG_DIRECT_IO) {
+ sg_remove_request(sfp, srp);
+ return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
+ }
+ if (sg_res_in_use(sfp)) {
+ sg_remove_request(sfp, srp);
+ return -EBUSY; /* reserve buffer already being used */
+ }
+ }
timeout = sg_ms_to_jif(srp->header.timeout);
if ((! hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof(cmnd))) {
sg_remove_request(sfp, srp);
@@ -681,7 +698,6 @@
srp->my_cmdp = SRpnt;
q = &SRpnt->sr_device->request_queue;
SRpnt->sr_request.rq_dev = sdp->i_rdev;
- SRpnt->sr_request.rq_status = RQ_ACTIVE;
SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_cmd_len = hp->cmd_len;
if (! (hp->flags & SG_FLAG_LUN_INHIBIT)) {
@@ -849,7 +865,7 @@
result = get_user(val, (int *)arg);
if (result) return result;
if (val != sfp->reserve.bufflen) {
- if (sg_res_in_use(sfp))
+ if (sg_res_in_use(sfp) || sfp->mmap_called)
return -EBUSY;
sg_remove_scat(&sfp->reserve);
sg_build_reserve(sfp, val);
@@ -1030,6 +1046,146 @@
return (retval < 0) ? retval : 0;
}
+static inline unsigned char * sg_scatg2virt(const struct scatterlist * sclp)
+{
+ return (sclp && sclp->page) ?
+ (unsigned char *)page_address(sclp->page) + sclp->offset :
+ NULL;
+}
+
+static void sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish)
+{
+ void * page_ptr;
+ struct page * page;
+ int k, m;
+
+ SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, "
+ "scatg=%d\n", startFinish, rsv_schp->k_use_sg));
+ /* N.B. correction _not_ applied to base page of aech allocation */
+ if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
+ struct scatterlist * sclp = rsv_schp->buffer;
+
+ for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
+ for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
+ page_ptr = sg_scatg2virt(sclp) + m;
+ page = virt_to_page(page_ptr);
+ if (startFinish)
+ get_page(page); /* increment page count */
+ else {
+ if (page_count(page) > 0)
+ put_page_testzero(page); /* decrement page count */
+ }
+ }
+ }
+ }
+ else { /* reserve buffer is just a single allocation */
+ for (m = PAGE_SIZE; m < rsv_schp->bufflen; m += PAGE_SIZE) {
+ page_ptr = (unsigned char *)rsv_schp->buffer + m;
+ page = virt_to_page(page_ptr);
+ if (startFinish)
+ get_page(page); /* increment page count */
+ else {
+ if (page_count(page) > 0)
+ put_page_testzero(page); /* decrement page count */
+ }
+ }
+ }
+}
+
+static struct page * sg_vma_nopage(struct vm_area_struct *vma,
+ unsigned long addr, int unused)
+{
+ Sg_fd * sfp;
+ struct page * page = NOPAGE_SIGBUS;
+ void * page_ptr = NULL;
+ unsigned long offset;
+ Sg_scatter_hold * rsv_schp;
+
+ if ((NULL == vma) || (! (sfp = (Sg_fd *)vma->vm_private_data)))
+ return page;
+ rsv_schp = &sfp->reserve;
+ offset = addr - vma->vm_start;
+ if (offset >= rsv_schp->bufflen)
+ return page;
+ SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n",
+ offset, rsv_schp->k_use_sg));
+ if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
+ int k;
+ unsigned long sa = vma->vm_start;
+ unsigned long len;
+ struct scatterlist * sclp = rsv_schp->buffer;
+
+ for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+ ++k, ++sclp) {
+ len = vma->vm_end - sa;
+ len = (len < sclp->length) ? len : sclp->length;
+ if (offset < len) {
+ page_ptr = sg_scatg2virt(sclp) + offset;
+ page = virt_to_page(page_ptr);
+ get_page(page); /* increment page count */
+ break;
+ }
+ sa += len;
+ offset -= len;
+ }
+ }
+ else { /* reserve buffer is just a single allocation */
+ page_ptr = (unsigned char *)rsv_schp->buffer + offset;
+ page = virt_to_page(page_ptr);
+ get_page(page); /* increment page count */
+ }
+ return page;
+}
+
+static struct vm_operations_struct sg_mmap_vm_ops = {
+ nopage : sg_vma_nopage,
+};
+
+static int sg_mmap(struct file * filp, struct vm_area_struct *vma)
+{
+ Sg_fd * sfp;
+ unsigned long req_sz = vma->vm_end - vma->vm_start;
+ Sg_scatter_hold * rsv_schp;
+
+ if ((! filp) || (! vma) || (! (sfp = (Sg_fd *)filp->private_data)))
+ return -ENXIO;
+ SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n",
+ (void *)vma->vm_start, (int)req_sz));
+ if (vma->vm_pgoff)
+ return -EINVAL; /* want no offset */
+ rsv_schp = &sfp->reserve;
+ if (req_sz > rsv_schp->bufflen)
+ return -ENOMEM; /* cannot map more than reserved buffer */
+
+ if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
+ int k;
+ unsigned long sa = vma->vm_start;
+ unsigned long len;
+ struct scatterlist * sclp = rsv_schp->buffer;
+
+ for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+ ++k, ++sclp) {
+ if (0 != sclp->offset)
+ return -EFAULT; /* non page aligned memory ?? */
+ len = vma->vm_end - sa;
+ len = (len < sclp->length) ? len : sclp->length;
+ sa += len;
+ }
+ }
+ else { /* reserve buffer is just a single allocation */
+ if ((unsigned long)rsv_schp->buffer & (PAGE_SIZE - 1))
+ return -EFAULT; /* non page aligned memory ?? */
+ }
+ if (0 == sfp->mmap_called) {
+ sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */
+ sfp->mmap_called = 1;
+ }
+ vma->vm_flags |= (VM_RESERVED | VM_IO);
+ vma->vm_private_data = sfp;
+ vma->vm_ops = &sg_mmap_vm_ops;
+ return 0;
+}
+
/* This function is a "bottom half" handler that is called by the
* mid level when a command is completed (or has failed). */
static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
@@ -1076,7 +1232,14 @@
srp->data.sglist_len = SRpnt->sr_sglist_len;
srp->data.bufflen = SRpnt->sr_bufflen;
srp->data.buffer = SRpnt->sr_buffer;
- sg_clr_srpnt(SRpnt);
+ /* now clear out request structure */
+ SRpnt->sr_use_sg = 0;
+ SRpnt->sr_sglist_len = 0;
+ SRpnt->sr_bufflen = 0;
+ SRpnt->sr_buffer = NULL;
+ SRpnt->sr_underflow = 0;
+ SRpnt->sr_request.rq_dev = mk_kdev(0, 0); /* "sg" _disowns_ request blk */
+
srp->my_cmdp = NULL;
srp->done = 1;
read_unlock(&sg_dev_arr_lock);
@@ -1121,14 +1284,15 @@
if (NULL == sfp->headrp) {
SCSI_LOG_TIMEOUT(1,
printk("sg...bh: already closed, final cleanup\n"));
- sg_remove_sfp(sdp, sfp);
+ if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
+ sdp->device->access_count--;
+ if (sdp->device->host->hostt->module)
+ __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
+ }
+ if (sg_template.module)
+ __MOD_DEC_USE_COUNT(sg_template.module);
sfp = NULL;
}
- sdp->device->access_count--;
- if (sg_template.module)
- __MOD_DEC_USE_COUNT(sg_template.module);
- if (sdp->device->host->hostt->module)
- __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
}
else if (srp && srp->orphan) {
if (sfp->keep_orphan)
@@ -1152,6 +1316,7 @@
poll: sg_poll,
ioctl: sg_ioctl,
open: sg_open,
+ mmap: sg_mmap,
release: sg_release,
fasync: sg_fasync,
};
@@ -1176,7 +1341,7 @@
if(!sg_registered) {
if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
{
- printk("Unable to get major %d for generic SCSI device\n",
+ printk(KERN_ERR "Unable to get major %d for generic SCSI device\n",
SCSI_GENERIC_MAJOR);
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
return 1;
@@ -1189,7 +1354,7 @@
sg_dev_arr = (Sg_device **)kmalloc(sg_template.dev_max *
sizeof(Sg_device *), GFP_ATOMIC);
if (NULL == sg_dev_arr) {
- printk("sg_init: no space for sg_dev_arr\n");
+ printk(KERN_ERR "sg_init: no space for sg_dev_arr\n");
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
return 1;
}
@@ -1212,8 +1377,8 @@
sg_big_buff = tmp;
return 1;
} else {
- printk("sg_def_reserved_size : usage sg_def_reserved_size=n "
- "(n could be 65536, 131072 or 262144)\n");
+ printk(KERN_WARNING "sg_def_reserved_size : usage "
+ "sg_def_reserved_size=n (n could be 65536, 131072 or 262144)\n");
return 0;
}
}
@@ -1238,7 +1403,7 @@
if (NULL == tmp_da) {
scsidp->attached--;
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
- printk("sg_attach: device array cannot be resized\n");
+ printk(KERN_ERR "sg_attach: device array cannot be resized\n");
return 1;
}
memset(tmp_da, 0, tmp_dev_max * sizeof(Sg_device *));
@@ -1250,13 +1415,13 @@
for(k = 0; k < sg_template.dev_max; k++)
if(! sg_dev_arr[k]) break;
- if (k > MINORMASK) {
+ if (k > SG_MAX_DEVS_MASK) {
scsidp->attached--;
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
- printk("Unable to attach sg device <%d, %d, %d, %d>"
+ printk(KERN_WARNING "Unable to attach sg device <%d, %d, %d, %d>"
" type=%d, minor number exceed %d\n", scsidp->host->host_no,
scsidp->channel, scsidp->id, scsidp->lun, scsidp->type,
- MINORMASK);
+ SG_MAX_DEVS_MASK);
return 1;
}
if(k < sg_template.dev_max)
@@ -1266,7 +1431,7 @@
if (NULL == sdp) {
scsidp->attached--;
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
- printk("sg_attach: Sg_device cannot be allocated\n");
+ printk(KERN_ERR "sg_attach: Sg_device cannot be allocated\n");
return 1;
}
@@ -1293,8 +1458,8 @@
case TYPE_WORM:
case TYPE_TAPE: break;
default:
- printk("Attached scsi generic sg%d at scsi%d, channel %d, id %d,"
- " lun %d, type %d\n", k, scsidp->host->host_no,
+ printk(KERN_NOTICE "Attached scsi generic sg%d at scsi%d, channel"
+ " %d, id %d, lun %d, type %d\n", k, scsidp->host->host_no,
scsidp->channel, scsidp->id, scsidp->lun, scsidp->type);
}
return 0;
@@ -1371,7 +1536,10 @@
MODULE_AUTHOR("Douglas Gilbert");
MODULE_DESCRIPTION("SCSI generic (sg) driver");
+
+#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
+#endif
MODULE_PARM(def_reserved_size, "i");
MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
@@ -1417,9 +1585,8 @@
if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */
return res;
}
- if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) {
+ if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen))
sg_link_reserve(sfp, srp, dxfer_len);
- }
else {
res = sg_build_indi(req_schp, sfp, dxfer_len);
if (res) {
@@ -1445,23 +1612,24 @@
sg_remove_request(sfp, srp);
}
-static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp)
+static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
+ int tablesize)
{
int mem_src, ret_sz;
- int sg_bufflen = PAGE_SIZE;
int elem_sz = sizeof(struct scatterlist) + sizeof(char);
- int mx_sc_elems = (sg_bufflen / elem_sz) - 1;
+ /* scatter gather array, followed by mem_src_arr (array of chars) */
+ int sg_bufflen = tablesize * elem_sz;
+ int mx_sc_elems = tablesize;
mem_src = SG_HEAP_KMAL;
- schp->buffer = (struct scatterlist *)sg_malloc(sfp, sg_bufflen,
- &ret_sz, &mem_src);
- schp->buffer_mem_src = (char)mem_src;
+ schp->buffer = sg_malloc(sfp, sg_bufflen, &ret_sz, &mem_src);
if (! schp->buffer)
return -ENOMEM;
else if (ret_sz != sg_bufflen) {
sg_bufflen = ret_sz;
- mx_sc_elems = (sg_bufflen / elem_sz) - 1;
+ mx_sc_elems = sg_bufflen / elem_sz;
}
+ schp->buffer_mem_src = (char)mem_src;
schp->sglist_len = sg_bufflen;
memset(schp->buffer, 0, sg_bufflen);
return mx_sc_elems; /* number of scat_gath elements allocated */
@@ -1470,13 +1638,15 @@
static void sg_unmap_and(Sg_scatter_hold * schp, int free_also)
{
#ifdef SG_ALLOW_DIO_CODE
+ int nbhs = 0;
+
if (schp && schp->kiobp) {
if (schp->mapped) {
unmap_kiobuf(schp->kiobp);
schp->mapped = 0;
}
if (free_also) {
- free_kiovec(1, &schp->kiobp);
+ sg_free_kiovec(1, &schp->kiobp, &nbhs);
schp->kiobp = NULL;
}
}
@@ -1494,10 +1664,12 @@
sg_io_hdr_t * hp = &srp->header;
Sg_scatter_hold * schp = &srp->data;
int sg_tablesize = sfp->parentdp->sg_tablesize;
+ int nbhs = 0;
- res = alloc_kiovec(1, &schp->kiobp);
+ res = sg_alloc_kiovec(1, &schp->kiobp, &nbhs);
if (0 != res) {
- SCSI_LOG_TIMEOUT(5, printk("sg_build_dir: alloc_kiovec res=%d\n", res));
+ SCSI_LOG_TIMEOUT(5, printk("sg_build_dir: sg_alloc_kiovec res=%d\n",
+ res));
return 1;
}
res = map_user_kiobuf((SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0,
@@ -1527,7 +1699,7 @@
hp->info |= SG_INFO_DIRECT_IO;
return 0;
}
- mx_sc_elems = sg_build_sgat(schp, sfp);
+ mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
if (mx_sc_elems <= 1) {
sg_unmap_and(schp, 1);
sg_remove_scat(schp);
@@ -1535,19 +1707,22 @@
}
mem_src_arr = schp->buffer + (mx_sc_elems * sizeof(struct scatterlist));
for (k = 0, sclp = schp->buffer, rem_sz = dxfer_len;
- (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
+ (rem_sz > 0) && (k < mx_sc_elems);
++k, ++sclp) {
offset = (0 == k) ? kp->offset : 0;
num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) :
rem_sz;
+ sclp->page = kp->maplist[k];
+ sclp->offset = offset;
+#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
sclp->address = page_address(kp->maplist[k]) + offset;
- sclp->page = NULL;
+#endif
sclp->length = num;
mem_src_arr[k] = SG_USER_MEM;
rem_sz -= num;
SCSI_LOG_TIMEOUT(5,
printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
- k, sclp->address, num, mem_src_arr[k]));
+ k, sg_scatg2virt(sclp), num, mem_src_arr[k]));
}
schp->k_use_sg = k;
SCSI_LOG_TIMEOUT(5,
@@ -1569,7 +1744,7 @@
{
int ret_sz, mem_src;
int blk_size = buff_size;
- char * p = NULL;
+ unsigned char * p = NULL;
if ((blk_size < 0) || (! sfp))
return -EFAULT;
@@ -1609,14 +1784,14 @@
char * mem_src_arr;
/* N.B. ret_sz and mem_src carried into this block ... */
- mx_sc_elems = sg_build_sgat(schp, sfp);
+ mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
if (mx_sc_elems < 0)
return mx_sc_elems; /* most likely -ENOMEM */
mem_src_arr = schp->buffer +
(mx_sc_elems * sizeof(struct scatterlist));
for (k = 0, sclp = schp->buffer, rem_sz = blk_size;
- (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
+ (rem_sz > 0) && (k < mx_sc_elems);
++k, rem_sz -= ret_sz, ++sclp) {
if (first)
first = 0;
@@ -1627,14 +1802,17 @@
if (! p)
break;
}
+ sclp->page = virt_to_page(p);
+ sclp->offset = (unsigned long)p & ~PAGE_MASK;
+#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
sclp->address = p;
- sclp->page = NULL;
+#endif
sclp->length = ret_sz;
mem_src_arr[k] = mem_src;
SCSI_LOG_TIMEOUT(5,
printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
- k, sclp->address, ret_sz, mem_src));
+ k, sg_scatg2virt(sclp), ret_sz, mem_src));
} /* end of for loop */
schp->k_use_sg = k;
SCSI_LOG_TIMEOUT(5,
@@ -1664,7 +1842,8 @@
if (schp->bufflen < num_xfer)
num_xfer = schp->bufflen;
}
- if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags)))
+ if ((num_xfer <= 0) ||
+ (new_interface && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
return 0;
SCSI_LOG_TIMEOUT(4,
@@ -1698,14 +1877,15 @@
struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
char * mem_src_arr = sg_get_sgat_msa(schp);
ksglen = (int)sclp->length;
- p = sclp->address;
+ p = sg_scatg2virt(sclp);
for (j = 0, k = 0; j < onum; ++j) {
res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
if (res) return res;
for (; (k < schp->k_use_sg) && p;
- ++k, ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
+ ++k, ++sclp, ksglen = (int)sclp->length,
+ p = sg_scatg2virt(sclp)) {
ok = (SG_USER_MEM != mem_src_arr[k]);
if (usglen <= 0)
break;
@@ -1766,7 +1946,7 @@
static char * sg_get_sgat_msa(Sg_scatter_hold * schp)
{
int elem_sz = sizeof(struct scatterlist) + sizeof(char);
- int mx_sc_elems = (schp->sglist_len / elem_sz) - 1;
+ int mx_sc_elems = schp->sglist_len / elem_sz;
return schp->buffer + (sizeof(struct scatterlist) * mx_sc_elems);
}
@@ -1779,14 +1959,17 @@
struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
char * mem_src_arr = sg_get_sgat_msa(schp);
- for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
+ for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp); ++k, ++sclp) {
mem_src = mem_src_arr[k];
SCSI_LOG_TIMEOUT(5,
printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n",
- k, sclp->address, sclp->length, mem_src));
- sg_free(sclp->address, sclp->length, mem_src);
- sclp->address = NULL;
+ k, sg_scatg2virt(sclp), sclp->length, mem_src));
+ sg_free(sg_scatg2virt(sclp), sclp->length, mem_src);
sclp->page = NULL;
+ sclp->offset = 0;
+#ifdef SG_STILL_HAVE_ADDRESS_IN_SCATTERLIST
+ sclp->address = 0;
+#endif
sclp->length = 0;
}
sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src);
@@ -1814,7 +1997,8 @@
if (schp->bufflen < num_xfer)
num_xfer = schp->bufflen;
}
- if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags)))
+ if ((num_xfer <= 0) ||
+ (new_interface && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
return 0;
SCSI_LOG_TIMEOUT(4,
@@ -1848,14 +2032,15 @@
struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
char * mem_src_arr = sg_get_sgat_msa(schp);
ksglen = (int)sclp->length;
- p = sclp->address;
+ p = sg_scatg2virt(sclp);
for (j = 0, k = 0; j < onum; ++j) {
res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
if (res) return res;
for (; (k < schp->k_use_sg) && p;
- ++k, ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
+ ++k, ++sclp, ksglen = (int)sclp->length,
+ p = sg_scatg2virt(sclp)) {
ok = (SG_USER_MEM != mem_src_arr[k]);
if (usglen <= 0)
break;
@@ -1896,14 +2081,14 @@
int k, num;
struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
- for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
+ for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp); ++k, ++sclp) {
num = (int)sclp->length;
if (num > num_read_xfer) {
- __copy_to_user(outp, sclp->address, num_read_xfer);
+ __copy_to_user(outp, sg_scatg2virt(sclp), num_read_xfer);
break;
}
else {
- __copy_to_user(outp, sclp->address, num);
+ __copy_to_user(outp, sg_scatg2virt(sclp), num);
num_read_xfer -= num;
if (num_read_xfer <= 0)
break;
@@ -1949,7 +2134,7 @@
if (rem <= num) {
if (0 == k) {
req_schp->k_use_sg = 0;
- req_schp->buffer = sclp->address;
+ req_schp->buffer = sg_scatg2virt(sclp);
}
else {
sfp->save_scat_len = num;
@@ -2189,6 +2374,8 @@
if (sfp->reserve.bufflen > 0) {
SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n",
(int)sfp->reserve.bufflen, (int)sfp->reserve.k_use_sg));
+ if (sfp->mmap_called)
+ sg_rb_correct4mmap(&sfp->reserve, 0); /* undo correction */
sg_remove_scat(&sfp->reserve);
}
sfp->parentdp = NULL;
@@ -2237,7 +2424,7 @@
/* MOD_INC's to inhibit unloading sg and associated adapter driver */
if (sg_template.module)
__MOD_INC_USE_COUNT(sg_template.module);
- if (sdp->device->host->hostt->module)
+ if (sdp->device->host->hostt->module)
__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
SCSI_LOG_TIMEOUT(1, printk(
"sg_remove_sfp: worrisome, %d writes pending\n", dirty));
@@ -2270,30 +2457,6 @@
if (resp && retSzp) *retSzp = rqSz;
return resp;
}
- if (SG_HEAP_POOL == mem_src) {
- int num_sect = rqSz / SG_SECTOR_SZ;
-
- if (0 != (rqSz & SG_SECTOR_MSK)) {
- if (! retSzp)
- return resp;
- ++num_sect;
- rqSz = num_sect * SG_SECTOR_SZ;
- }
- while (num_sect > 0) {
- if ((num_sect <= sg_pool_secs_avail)) {
- resp = kmalloc(rqSz, page_mask);
- if (resp) {
- if (retSzp) *retSzp = rqSz;
- sg_pool_secs_avail -= num_sect;
- return resp;
- }
- }
- if (! retSzp)
- return resp;
- num_sect /= 2; /* try half as many */
- rqSz = num_sect * SG_SECTOR_SZ;
- }
- }
else if (SG_HEAP_PAGE == mem_src) {
int order, a_size;
int resSz = rqSz;
@@ -2311,7 +2474,8 @@
if (retSzp) *retSzp = resSz;
}
else
- printk("sg_low_malloc: bad mem_src=%d, rqSz=%df\n", mem_src, rqSz);
+ printk(KERN_ERR "sg_low_malloc: bad mem_src=%d, rqSz=%df\n",
+ mem_src, rqSz);
return resp;
}
@@ -2330,29 +2494,20 @@
switch (*mem_srcp)
{
case SG_HEAP_PAGE:
- l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
+ l_ms = (size < PAGE_SIZE) ? SG_HEAP_KMAL : SG_HEAP_PAGE;
resp = sg_low_malloc(size, low_dma, l_ms, 0);
if (resp)
break;
resp = sg_low_malloc(size, low_dma, l_ms, &size);
if (! resp) {
- l_ms = (SG_HEAP_POOL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_POOL;
+ l_ms = (SG_HEAP_KMAL == l_ms) ? SG_HEAP_PAGE : SG_HEAP_KMAL;
resp = sg_low_malloc(size, low_dma, l_ms, &size);
- if (! resp) {
- l_ms = SG_HEAP_KMAL;
- resp = sg_low_malloc(size, low_dma, l_ms, &size);
- }
}
if (resp && retSzp) *retSzp = size;
break;
case SG_HEAP_KMAL:
- l_ms = SG_HEAP_PAGE;
+ l_ms = SG_HEAP_KMAL; /* was SG_HEAP_PAGE */
resp = sg_low_malloc(size, low_dma, l_ms, 0);
- if (resp)
- break;
- l_ms = SG_HEAP_POOL;
- resp = sg_low_malloc(size, low_dma, l_ms, &size);
- if (resp && retSzp) *retSzp = size;
break;
default:
SCSI_LOG_TIMEOUT(1, printk("sg_malloc: bad ms=%d\n", *mem_srcp));
@@ -2365,18 +2520,19 @@
return resp;
}
+static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp)
+{
+#if SG_NEW_KIOVEC
+ return alloc_kiovec_sz(nr, bufp, szp);
+#else
+ return alloc_kiovec(nr, bufp);
+#endif
+}
+
static void sg_low_free(char * buff, int size, int mem_src)
{
if (! buff) return;
switch (mem_src) {
- case SG_HEAP_POOL:
- {
- int num_sect = size / SG_SECTOR_SZ;
-
- kfree(buff);
- sg_pool_secs_avail += num_sect;
- }
- break;
case SG_HEAP_KMAL:
kfree(buff); /* size not used */
break;
@@ -2392,7 +2548,7 @@
case SG_USER_MEM:
break; /* nothing to do */
default:
- printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%d\n",
+ printk(KERN_ERR "sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%d\n",
mem_src, buff, size);
break;
}
@@ -2408,14 +2564,13 @@
sg_low_free(buff, size, mem_src);
}
-static void sg_clr_srpnt(Scsi_Request * SRpnt)
+static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp)
{
- SRpnt->sr_use_sg = 0;
- SRpnt->sr_sglist_len = 0;
- SRpnt->sr_bufflen = 0;
- SRpnt->sr_buffer = NULL;
- SRpnt->sr_underflow = 0;
- SRpnt->sr_request.rq_dev = mk_kdev(0, 0); /* "sg" _disowns_ command blk */
+#if SG_NEW_KIOVEC
+ free_kiovec_sz(nr, bufp, szp);
+#else
+ free_kiovec(nr, bufp);
+#endif
}
static int sg_ms_to_jif(unsigned int msecs)
@@ -2427,7 +2582,7 @@
: (((int)msecs / 1000) * HZ);
}
-static unsigned sg_jif_to_ms(int jifs)
+static inline unsigned sg_jif_to_ms(int jifs)
{
if (jifs <= 0)
return 0U;
@@ -2477,8 +2632,8 @@
if (sg_dev_arr && (dev >= 0))
{
read_lock_irqsave(&sg_dev_arr_lock, iflags);
- if (dev < sg_template.dev_max)
- sdp = sg_dev_arr[dev];
+ if (dev < sg_template.dev_max)
+ sdp = sg_dev_arr[dev];
read_unlock_irqrestore(&sg_dev_arr_lock, iflags);
}
return sdp;
@@ -2671,7 +2826,7 @@
{
Sg_device * sdp;
const sg_io_hdr_t * hp;
- int j, max_dev;
+ int j, max_dev, new_interface;
if (NULL == sg_dev_arr) {
PRINT_PROC("sg_dev_arr NULL, driver not initialized\n");
@@ -2680,8 +2835,7 @@
max_dev = sg_last_dev();
PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n",
sg_template.dev_max, max_dev);
- PRINT_PROC(" sg_pool_secs_aval=%d def_reserved_size=%d\n",
- sg_pool_secs_avail, sg_big_buff);
+ PRINT_PROC(" def_reserved_size=%d\n", sg_big_buff);
for (j = 0; j < max_dev; ++j) {
if ((sdp = sg_get_dev(j))) {
Sg_fd * fp;
@@ -2717,8 +2871,10 @@
(int)fp->keep_orphan, (int)fp->closed);
for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) {
hp = &srp->header;
+ new_interface = (hp->interface_id == '\0') ? 0 : 1;
/* stop indenting so far ... */
- PRINT_PROC(srp->res_used ? " rb>> " :
+ PRINT_PROC(srp->res_used ? ((new_interface &&
+ (SG_FLAG_MMAP_IO & hp->flags)) ? " mmap>> " : " rb>> ") :
((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " "));
blen = srp->my_cmdp ? srp->my_cmdp->sr_bufflen : srp->data.bufflen;
usg = srp->my_cmdp ? srp->my_cmdp->sr_use_sg : srp->data.k_use_sg;
@@ -2728,8 +2884,8 @@
if (srp->done)
PRINT_PROC(" dur=%d", hp->duration);
else
- PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ?
- sg_jif_to_ms(fp->timeout) : hp->timeout),
+ PRINT_PROC(" t_o/elap=%d/%d", new_interface ? hp->timeout :
+ sg_jif_to_ms(fp->timeout),
sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
PRINT_PROC("ms sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode);
/* reset indenting */
diff -u --recursive --new-file pre1/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- pre1/linux/drivers/scsi/sr.c Thu Jan 3 11:35:33 2002
+++ linux/drivers/scsi/sr.c Thu Jan 17 13:59:33 2002
@@ -331,7 +331,7 @@
SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
devm,
- (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
+ (rq_data_dir(&SCpnt->request) == WRITE) ? "writing" : "reading",
this_count, SCpnt->request.nr_sectors));
SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
diff -u --recursive --new-file pre1/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- pre1/linux/drivers/sound/via82cxxx_audio.c Mon Dec 10 10:39:20 2001
+++ linux/drivers/sound/via82cxxx_audio.c Tue Jan 15 13:53:51 2002
@@ -1995,7 +1995,7 @@
/* just to be a nice neighbor */
/* Thomas Sailer:
* But also to ourselves, release semaphore if we do so */
- if (current->need_resched) {
+ if (need_resched()) {
up(&card->syscall_sem);
schedule ();
ret = via_syscall_down (card, nonblock);
@@ -2171,7 +2171,7 @@
/* just to be a nice neighbor */
/* Thomas Sailer:
* But also to ourselves, release semaphore if we do so */
- if (current->need_resched) {
+ if (need_resched()) {
up(&card->syscall_sem);
schedule ();
ret = via_syscall_down (card, nonblock);
diff -u --recursive --new-file pre1/linux/drivers/tc/tc.c linux/drivers/tc/tc.c
--- pre1/linux/drivers/tc/tc.c Thu Oct 11 09:43:30 2001
+++ linux/drivers/tc/tc.c Thu Jan 17 14:21:16 2002
@@ -236,6 +236,8 @@
}
}
+subsys_initcall(tc_init);
+
EXPORT_SYMBOL(search_tc_card);
EXPORT_SYMBOL(claim_tc_card);
EXPORT_SYMBOL(release_tc_card);
diff -u --recursive --new-file pre1/linux/drivers/usb/hcd/ehci-hcd.c linux/drivers/usb/hcd/ehci-hcd.c
--- pre1/linux/drivers/usb/hcd/ehci-hcd.c Mon Jan 14 10:10:43 2002
+++ linux/drivers/usb/hcd/ehci-hcd.c Thu Jan 17 14:06:53 2002
@@ -70,9 +70,15 @@
* Brad Hards
* Rory Bolt
* ...
+ *
+ * HISTORY:
+ * 2002-01-14 Minor cleanup; version synch.
+ * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers.
+ * 2002-01-04 Control/Bulk queuing behaves.
+ * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
*/
-#define DRIVER_VERSION "$Revision: 0.25 $"
+#define DRIVER_VERSION "$Revision: 0.26 $"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
@@ -97,9 +103,6 @@
static int log2_irq_thresh = 0; // 0 to 6
MODULE_PARM (log2_irq_thresh, "i");
MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
-/* Some A steppings of the NEC controller need soft retries */
-//#define EHCI_SOFT_RETRIES 5 /* after CERR-induced fault */
#define INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT)
diff -u --recursive --new-file pre1/linux/drivers/usb/hcd/ehci-hub.c linux/drivers/usb/hcd/ehci-hub.c
--- pre1/linux/drivers/usb/hcd/ehci-hub.c Tue Jan 1 13:52:10 2002
+++ linux/drivers/usb/hcd/ehci-hub.c Thu Jan 17 14:06:53 2002
@@ -82,11 +82,12 @@
for (i = 0; i < ports; i++) {
temp = readl (&ehci->regs->port_status [i]);
if (temp & PORT_OWNER) {
- // get disconnected ports back if no companion driver
- if (temp & PORT_CONNECT)
- continue;
- temp &= ~(PORT_OWNER|PORT_CSC);
- writel (temp, &ehci->regs->port_status [i]);
+ /* don't report this in GetPortStatus */
+ if (temp & PORT_CSC) {
+ temp &= ~PORT_CSC;
+ writel (temp, &ehci->regs->port_status [i]);
+ }
+ continue;
}
if (!(temp & PORT_CONNECT))
ehci->reset_done [i] = 0;
diff -u --recursive --new-file pre1/linux/drivers/usb/hcd/ehci-q.c linux/drivers/usb/hcd/ehci-q.c
--- pre1/linux/drivers/usb/hcd/ehci-q.c Tue Jan 8 13:15:52 2002
+++ linux/drivers/usb/hcd/ehci-q.c Thu Jan 17 14:06:53 2002
@@ -883,11 +883,10 @@
/* can't get here without STS_ASS set */
if (ehci->hcd.state != USB_STATE_HALT) {
if (cmd & CMD_PSE)
- writel (cmd & __constant_cpu_to_le32 (~CMD_ASE),
- &ehci->regs->command);
+ writel (cmd & ~CMD_ASE, &ehci->regs->command);
else {
ehci_ready (ehci);
- while (!(readl (&ehci->regs->status) & STS_ASS))
+ while (readl (&ehci->regs->status) & STS_ASS)
udelay (100);
}
}
diff -u --recursive --new-file pre1/linux/drivers/usb/hcd/ehci-sched.c linux/drivers/usb/hcd/ehci-sched.c
--- pre1/linux/drivers/usb/hcd/ehci-sched.c Mon Jan 14 10:10:43 2002
+++ linux/drivers/usb/hcd/ehci-sched.c Thu Jan 17 14:06:53 2002
@@ -381,7 +381,7 @@
vdbg ("qh %p usecs %d period %d starting frame %d.%d",
qh, qh->usecs, period, frame, uframe);
do {
- if (unlikely ((long)ehci->pshadow [frame].ptr)) {
+ if (unlikely (ehci->pshadow [frame].ptr != 0)) {
// FIXME -- just link to the end, before any qh with a shorter period,
// AND handle it already being (implicitly) linked into this frame
BUG ();
diff -u --recursive --new-file pre1/linux/drivers/usb/hcd.c linux/drivers/usb/hcd.c
--- pre1/linux/drivers/usb/hcd.c Mon Jan 14 10:10:43 2002
+++ linux/drivers/usb/hcd.c Thu Jan 17 14:06:53 2002
@@ -1081,20 +1081,20 @@
if (!urb)
return -EINVAL;
- // FIXME: add some explicit records to flag the
- // state where the URB is "in periodic completion".
- // Workaround is for driver to set the urb status
- // to "-EINPROGRESS", so it can get through here
- // and unlink from the completion handler.
-
/*
* we contend for urb->status with the hcd core,
* which changes it while returning the urb.
+ *
+ * Caller guaranteed that the urb pointer hasn't been freed, and
+ * that it was submitted. But as a rule it can't know whether or
+ * not it's already been unlinked ... so we respect the reversed
+ * lock sequence needed for the usb_hcd_giveback_urb() code paths
+ * (urb lock, then hcd_data_lock) in case some other CPU is now
+ * unlinking it.
*/
spin_lock_irqsave (&urb->lock, flags);
- if (!urb->hcpriv
- || urb->status != -EINPROGRESS
- || urb->transfer_flags & USB_TIMEOUT_KILLED) {
+ spin_lock (&hcd_data_lock);
+ if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) {
retval = -EINVAL;
goto done;
}
@@ -1103,6 +1103,8 @@
retval = -ENODEV;
goto done;
}
+
+ /* giveback clears dev; non-null means it's linked at this level */
dev = urb->dev->hcpriv;
hcd = urb->dev->bus->hcpriv;
if (!dev || !hcd) {
@@ -1110,6 +1112,27 @@
goto done;
}
+ /* For non-periodic transfers, any status except -EINPROGRESS means
+ * the HCD has already started to unlink this URB from the hardware.
+ * In that case, there's no more work to do.
+ *
+ * For periodic transfers, this is the only way to trigger unlinking
+ * from the hardware. Since we (currently) overload urb->status to
+ * tell the driver to unlink, error status might get clobbered ...
+ * unless that transfer hasn't yet restarted. One such case is when
+ * the URB gets unlinked from its completion handler.
+ *
+ * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
+ */
+ switch (usb_pipetype (urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ if (urb->status != -EINPROGRESS) {
+ retval = 0;
+ goto done;
+ }
+ }
+
/* maybe set up to block on completion notification */
if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
urb->status = -ETIMEDOUT;
@@ -1130,6 +1153,7 @@
/* asynchronous unlink */
urb->status = -ECONNRESET;
}
+ spin_unlock (&hcd_data_lock);
spin_unlock_irqrestore (&urb->lock, flags);
if (urb == (struct urb *) hcd->rh_timer.data) {
@@ -1154,6 +1178,7 @@
}
goto bye;
done:
+ spin_unlock (&hcd_data_lock);
spin_unlock_irqrestore (&urb->lock, flags);
bye:
if (retval)
diff -u --recursive --new-file pre1/linux/drivers/usb/hpusbscsi.c linux/drivers/usb/hpusbscsi.c
--- pre1/linux/drivers/usb/hpusbscsi.c Tue Dec 25 17:04:40 2001
+++ linux/drivers/usb/hpusbscsi.c Thu Jan 17 14:06:53 2002
@@ -272,7 +272,7 @@
if (!srb->bufflen) {
usb_callback = simple_command_callback;
} else {
- if (srb->use_sg) {
+ if (likely(srb->use_sg)) {
usb_callback = scatter_gather_callback;
hpusbscsi->fragment = 0;
} else {
@@ -288,10 +288,6 @@
TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_FREE) {
- printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!\n");
- return 1; /* This must not happen */
- }
/* We zero the sense buffer to avoid confusing user space */
memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
@@ -313,10 +309,10 @@
hpusbscsi->srb = srb;
res = usb_submit_urb(&hpusbscsi->dataurb);
- if (res) {
+ if (unlikely(res)) {
hpusbscsi->state = HP_STATE_FREE;
TRACE_STATE;
- if (callback) {
+ if (likely(callback != NULL)) {
srb->result = DID_ERROR;
callback(srb);
}
@@ -355,7 +351,7 @@
static void handle_usb_error (struct hpusbscsi *hpusbscsi)
{
- if (hpusbscsi->scallback != NULL) {
+ if (likely(hpusbscsi->scallback != NULL)) {
hpusbscsi->srb->result = DID_ERROR;
hpusbscsi->scallback(hpusbscsi->srb);
}
@@ -367,8 +363,8 @@
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
- if(u->status < 0) {
- if (hpusbscsi->state != HP_STATE_FREE)
+ if(unlikely(u->status < 0)) {
+ if (likely(hpusbscsi->state != HP_STATE_FREE))
handle_usb_error(hpusbscsi);
return;
}
@@ -402,7 +398,7 @@
static void simple_command_callback(struct urb *u)
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- if (u->status<0) {
+ if (unlikely(u->status<0)) {
handle_usb_error(hpusbscsi);
return;
}
@@ -411,7 +407,7 @@
TRACE_STATE;
hpusbscsi->state = HP_STATE_WAIT;
} else {
- if (hpusbscsi->scallback != NULL)
+ if (likely(hpusbscsi->scallback != NULL))
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
TRACE_STATE;
@@ -426,7 +422,7 @@
int res;
DEBUG("Going through scatter/gather\n");
- if (u->status < 0) {
+ if (unlikely(u->status < 0)) {
handle_usb_error(hpusbscsi);
return;
}
@@ -452,7 +448,7 @@
);
res = usb_submit_urb(u);
- if (res)
+ if (unlikely(res))
hpusbscsi->state = HP_STATE_ERROR;
TRACE_STATE;
}
@@ -461,20 +457,20 @@
{
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- if (u->status < 0) {
+ if (unlikely(u->status < 0)) {
handle_usb_error(hpusbscsi);
return;
}
DEBUG("Data transfer done\n");
TRACE_STATE;
if (hpusbscsi->state != HP_STATE_PREMATURE) {
- if (u->status < 0)
+ if (unlikely(u->status < 0))
hpusbscsi->state = HP_STATE_ERROR;
else
hpusbscsi->state = HP_STATE_WAIT;
TRACE_STATE;
} else {
- if (hpusbscsi->scallback != NULL)
+ if (likely(hpusbscsi->scallback != NULL))
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
}
@@ -485,7 +481,7 @@
struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
int res;
- if (u->status<0) {
+ if (unlikely(u->status<0)) {
handle_usb_error(hpusbscsi);
return;
}
@@ -501,7 +497,7 @@
);
res = usb_submit_urb(u);
- if (res) {
+ if (unlikely(res)) {
handle_usb_error(hpusbscsi);
return;
}
@@ -510,10 +506,11 @@
hpusbscsi->state = HP_STATE_WORKING;
TRACE_STATE;
} else {
- if (hpusbscsi->scallback != NULL)
+ if (likely(hpusbscsi->scallback != NULL))
hpusbscsi->scallback(hpusbscsi->srb);
hpusbscsi->state = HP_STATE_FREE;
TRACE_STATE;
}
}
+
diff -u --recursive --new-file pre1/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- pre1/linux/drivers/usb/hub.c Tue Jan 1 13:52:10 2002
+++ linux/drivers/usb/hub.c Thu Jan 17 14:06:53 2002
@@ -557,6 +557,10 @@
dbg("port %d, portstatus %x, change %x, %s", port + 1,
portstatus, portchange, portspeed (portstatus));
+ /* Device went away? */
+ if (!(portstatus & USB_PORT_STAT_CONNECTION))
+ return 1;
+
/* bomb out completely if something weird happened */
if ((portchange & USB_PORT_STAT_C_CONNECTION))
return -1;
diff -u --recursive --new-file pre1/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c
--- pre1/linux/drivers/usb/microtek.c Tue Dec 25 17:04:40 2001
+++ linux/drivers/usb/microtek.c Thu Jan 17 14:06:53 2002
@@ -320,11 +320,6 @@
#endif
-
-/* static inline int mts_is_aborting(struct mts_desc* desc) {
- return (atomic_read(&desc->context.do_abort));
-} */
-
static inline void mts_urb_abort(struct mts_desc* desc) {
MTS_DEBUG_GOT_HERE();
mts_debug_dump(desc);
@@ -504,7 +499,7 @@
transfer->status = 0;
res = usb_submit_urb( transfer );
- if ( res ) {
+ if ( unlikely(res) ) {
MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
context->srb->result = DID_ERROR << 16;
mts_transfer_cleanup(transfer);
@@ -518,7 +513,7 @@
{
MTS_INT_INIT();
- if ( context->final_callback )
+ if ( likely(context->final_callback != NULL) )
context->final_callback(context->srb);
}
@@ -556,7 +551,7 @@
if ( context->data_length != transfer->actual_length ) {
context->srb->resid = context->data_length - transfer->actual_length;
- } else if ( transfer->status ) {
+ } else if ( unlikely(transfer->status) ) {
context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
}
@@ -571,7 +566,7 @@
{
MTS_INT_INIT();
- if ( transfer->status ) {
+ if ( unlikely(transfer->status) ) {
if (transfer->status == -ENOENT) {
/* We are being killed */
MTS_DEBUG_GOT_HERE();
@@ -605,7 +600,7 @@
MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
- if (transfer->status) {
+ if (unlikely(transfer->status)) {
context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
mts_transfer_cleanup(transfer);
}
@@ -703,7 +698,7 @@
srb->result = DID_BAD_TARGET << 16;
- if(callback)
+ if(likely(callback != NULL))
callback(srb);
goto out;
@@ -725,11 +720,11 @@
res=usb_submit_urb(&desc->urb);
- if(res){
+ if(unlikely(res)){
MTS_ERROR("error %d submitting URB\n",(int)res);
srb->result = DID_ERROR << 16;
- if(callback)
+ if(likely(callback != NULL))
callback(srb);
}
@@ -1061,4 +1056,5 @@
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
+
diff -u --recursive --new-file pre1/linux/drivers/usb/serial/ir-usb.c linux/drivers/usb/serial/ir-usb.c
--- pre1/linux/drivers/usb/serial/ir-usb.c Sun Jan 6 18:49:21 2002
+++ linux/drivers/usb/serial/ir-usb.c Thu Jan 17 14:06:53 2002
@@ -2,6 +2,7 @@
* USB IR Dongle driver
*
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +21,12 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * 2002_Jan_14 gb
+ * Added module parameter to force specific number of XBOFs.
+ * Added ir_xbof_change().
+ * Reorganized read_bulk_callback error handling.
+ * Switched from FILL_BULK_URB() to usb_fill_bulk_urb().
+ *
* 2001_Nov_08 greg kh
* Changed the irda_usb_find_class_desc() function based on comments and
* code from Martin Diehl.
@@ -62,13 +69,15 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.3"
+#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Greg Kroah-Hartman "
#define DRIVER_DESC "USB IR Dongle driver"
/* if overridden by the user, then use their value for the size of the read and
* write urbs */
static int buffer_size = 0;
+/* if overridden by the user, then use the specified number of XBOFs */
+static int xbof = -1;
static int ir_startup (struct usb_serial *serial);
static int ir_open (struct usb_serial_port *port, struct file *filep);
@@ -78,6 +87,9 @@
static void ir_read_bulk_callback (struct urb *urb);
static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static u8 ir_baud = 0;
+static u8 ir_xbof = 0;
+static u8 ir_add_bof = 0;
static __devinitdata struct usb_device_id id_table [] = {
{ USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */
@@ -148,14 +160,16 @@
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500));
- dbg(__FUNCTION__ " - ret=%d", ret);
+ dbg("%s - ret=%d", __FUNCTION__, ret);
if (ret < sizeof(*desc)) {
- dbg(__FUNCTION__ " - class descriptor read %s (%d)",
- (ret<0) ? "failed" : "too short", ret);
+ dbg("%s - class descriptor read %s (%d)",
+ __FUNCTION__,
+ (ret<0) ? "failed" : "too short",
+ ret);
goto error;
}
if (desc->bDescriptorType != USB_DT_IRDA) {
- dbg(__FUNCTION__ " - bad class descriptor type");
+ dbg("%s - bad class descriptor type", __FUNCTION__);
goto error;
}
@@ -166,6 +180,28 @@
return NULL;
}
+
+static u8 ir_xbof_change(u8 xbof)
+{
+ u8 result;
+ /* reference irda-usb.c */
+ switch(xbof) {
+ case 48: result = 0x10; break;
+ case 28:
+ case 24: result = 0x20; break;
+ default:
+ case 12: result = 0x30; break;
+ case 5:
+ case 6: result = 0x40; break;
+ case 3: result = 0x50; break;
+ case 2: result = 0x60; break;
+ case 1: result = 0x70; break;
+ case 0: result = 0x80; break;
+ }
+ return(result);
+}
+
+
static int ir_startup (struct usb_serial *serial)
{
struct irda_class_desc *irda_desc;
@@ -175,16 +211,30 @@
err ("IRDA class descriptor not found, device not bound");
return -ENODEV;
}
- dbg (__FUNCTION__" - Baud rates supported: %s%s%s%s%s%s%s%s%s",
- (irda_desc->wBaudRate & 0x0001) ? "2400 " : "",
- irda_desc->wBaudRate & 0x0002 ? "9600 " : "",
- irda_desc->wBaudRate & 0x0004 ? "19200 " : "",
- irda_desc->wBaudRate & 0x0008 ? "38400 " : "",
- irda_desc->wBaudRate & 0x0010 ? "57600 " : "",
- irda_desc->wBaudRate & 0x0020 ? "115200 " : "",
- irda_desc->wBaudRate & 0x0040 ? "576000 " : "",
- irda_desc->wBaudRate & 0x0080 ? "1152000 " : "",
- irda_desc->wBaudRate & 0x0100 ? "4000000 " : "");
+
+ dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+ __FUNCTION__,
+ (irda_desc->wBaudRate & 0x0001) ? " 2400" : "",
+ (irda_desc->wBaudRate & 0x0002) ? " 9600" : "",
+ (irda_desc->wBaudRate & 0x0004) ? " 19200" : "",
+ (irda_desc->wBaudRate & 0x0008) ? " 38400" : "",
+ (irda_desc->wBaudRate & 0x0010) ? " 57600" : "",
+ (irda_desc->wBaudRate & 0x0020) ? " 115200" : "",
+ (irda_desc->wBaudRate & 0x0040) ? " 576000" : "",
+ (irda_desc->wBaudRate & 0x0080) ? " 1152000" : "",
+ (irda_desc->wBaudRate & 0x0100) ? " 4000000" : "");
+
+ switch( irda_desc->bmAdditionalBOFs ) {
+ case 0x01: ir_add_bof = 48; break;
+ case 0x02: ir_add_bof = 24; break;
+ case 0x04: ir_add_bof = 12; break;
+ case 0x08: ir_add_bof = 6; break;
+ case 0x10: ir_add_bof = 3; break;
+ case 0x20: ir_add_bof = 2; break;
+ case 0x40: ir_add_bof = 1; break;
+ case 0x80: ir_add_bof = 0; break;
+ default:
+ }
kfree (irda_desc);
@@ -200,7 +250,7 @@
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
- dbg(__FUNCTION__ " - port %d", port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
down (&port->sem);
@@ -211,7 +261,7 @@
/* override the default buffer sizes */
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err (__FUNCTION__ " - out of memory.");
+ err ("%s - out of memory.", __FUNCTION__);
return -ENOMEM;
}
kfree (port->read_urb->transfer_buffer);
@@ -220,7 +270,7 @@
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err (__FUNCTION__ " - out of memory.");
+ err ("%s - out of memory.", __FUNCTION__);
return -ENOMEM;
}
kfree (port->write_urb->transfer_buffer);
@@ -230,13 +280,18 @@
}
/* Start reading from the device */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ir_read_bulk_callback, port);
+ usb_fill_bulk_urb (
+ port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ir_read_bulk_callback,
+ port);
+ port->read_urb->transfer_flags = USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb);
if (result)
- err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+ err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
}
up (&port->sem);
@@ -251,7 +306,7 @@
if (port_paranoia_check (port, __FUNCTION__))
return;
- dbg(__FUNCTION__ " - port %d", port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
serial = get_usb_serial (port, __FUNCTION__);
if (!serial)
@@ -276,11 +331,12 @@
{
unsigned char *transfer_buffer;
int result;
+ int transfer_size;
- dbg(__FUNCTION__ " - port = %d, count = %d", port->number, count);
+ dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
if (!port->tty) {
- err (__FUNCTION__ " - no tty???");
+ err ("%s - no tty???", __FUNCTION__);
return 0;
}
@@ -288,37 +344,49 @@
return 0;
if (port->write_urb->status == -EINPROGRESS) {
- dbg (__FUNCTION__ " - already writing");
+ dbg ("%s - already writing", __FUNCTION__);
return 0;
}
+ transfer_buffer = port->write_urb->transfer_buffer;
+ transfer_size = min(count, port->bulk_out_size - 1);
+
/*
- * The first byte of the packet we send to the device contains a BOD
- * and baud rate change. So we set it to 0.
+ * The first byte of the packet we send to the device contains an
+ * inband header which indicates an additional number of BOFs and
+ * a baud rate change.
+ *
* See section 5.4.2.2 of the USB IrDA spec.
*/
- transfer_buffer = port->write_urb->transfer_buffer;
- count = min (port->bulk_out_size-1, count);
+ *transfer_buffer = ir_xbof | ir_baud;
+ ++transfer_buffer;
+
if (from_user) {
- if (copy_from_user (&transfer_buffer[1], buf, count))
+ if (copy_from_user (transfer_buffer, buf, transfer_size))
return -EFAULT;
} else {
- memcpy (&transfer_buffer[1], buf, count);
+ memcpy (transfer_buffer, buf, transfer_size);
}
- /* use 12 XBOF's as default */
- transfer_buffer[0] = 0x30;
-
- usb_serial_debug_data (__FILE__, __FUNCTION__, count+1, transfer_buffer);
+ usb_fill_bulk_urb (
+ port->write_urb,
+ port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer,
+ transfer_size + 1,
+ ir_write_bulk_callback,
+ port);
+
+ port->write_urb->transfer_flags
+ = USB_QUEUE_BULK
+ | USB_ZERO_PACKET;
- port->write_urb->transfer_buffer_length = count + 1;
- port->write_urb->dev = port->serial->dev;
- port->write_urb->transfer_flags |= USB_ZERO_PACKET;
result = usb_submit_urb (port->write_urb);
if (result)
- err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+ err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else
- result = count;
+ result = transfer_size;
return result;
}
@@ -330,13 +398,19 @@
if (port_paranoia_check (port, __FUNCTION__))
return;
- dbg(__FUNCTION__ " - port %d", port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) {
- dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+ dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
return;
}
+ usb_serial_debug_data (
+ __FILE__,
+ __FUNCTION__,
+ urb->actual_length,
+ urb->transfer_buffer);
+
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
@@ -354,34 +428,87 @@
if (port_paranoia_check (port, __FUNCTION__))
return;
- dbg(__FUNCTION__ " - port %d", port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
if (!serial) {
- dbg(__FUNCTION__ " - bad serial pointer, exiting");
+ dbg("%s - bad serial pointer, exiting", __FUNCTION__);
return;
}
- if (urb->status) {
- dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+ if (!port->open_count) {
+ dbg("%s - port closed.", __FUNCTION__);
return;
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ switch (urb->status) {
+
+ case 0: /* Successful */
+
+ /*
+ * The first byte of the packet we get from the device
+ * contains a busy indicator and baud rate change.
+ * See section 5.4.1.2 of the USB IrDA spec.
+ */
+ if((*data & 0x0f) > 0) ir_baud = *data & 0x0f;
+
+ usb_serial_debug_data (
+ __FILE__,
+ __FUNCTION__,
+ urb->actual_length,
+ data);
+
+ /*
+ * Bypass flip-buffers, and feed the ldisc directly
+ * due to our potentally large buffer size. Since we
+ * used to set low_latency, this is exactly what the
+ * tty layer did anyway :)
+ */
+ tty = port->tty;
+
+ tty->ldisc.receive_buf(
+ tty,
+ data+1,
+ NULL,
+ urb->actual_length-1);
+
+ /*
+ * No break here.
+ * We want to resubmit the urb so we can read
+ * again.
+ */
+
+ case -EPROTO: /* taking inspiration from pl2303.c */
+
+ /* Continue trying to always read */
+ usb_fill_bulk_urb (
+ port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ir_read_bulk_callback,
+ port);
+
+ port->read_urb->transfer_flags = USB_QUEUE_BULK;
+
+ result = usb_submit_urb(port->read_urb);
+
+ if (result)
+ err("%s - failed resubmitting read urb, error %d",
+ __FUNCTION__,
+ result);
+
+ break ;
+
+ default:
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__,
+ urb->status);
+ break ;
+
+ }
- /* Bypass flip-buffers, and feed the ldisc directly due to our
- * potentally large buffer size. Since we used to set low_latency,
- * this is exactly what the tty layer did anyway :) */
- tty = port->tty;
- tty->ldisc.receive_buf(tty, data+1, NULL, urb->actual_length-1);
-
- /* Continue trying to always read */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ir_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb);
- if (result)
- err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
}
@@ -390,12 +517,11 @@
unsigned char *transfer_buffer;
unsigned int cflag;
int result;
- u8 baud;
- dbg(__FUNCTION__ " - port %d", port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
if ((!port->tty) || (!port->tty->termios)) {
- dbg(__FUNCTION__" - no tty structures");
+ dbg("%s - no tty structures", __FUNCTION__);
return;
}
@@ -404,44 +530,70 @@
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
(RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg(__FUNCTION__ " - nothing to change...");
+ dbg("%s - nothing to change...", __FUNCTION__);
return;
}
}
/* All we can change is the baud rate */
if (cflag & CBAUD) {
- dbg (__FUNCTION__ " - asking for baud %d", tty_get_baud_rate(port->tty));
+
+ dbg ("%s - asking for baud %d",
+ __FUNCTION__,
+ tty_get_baud_rate(port->tty));
+
/*
* FIXME, we should compare the baud request against the
* capability stated in the IR header that we got in the
* startup funtion.
*/
switch (cflag & CBAUD) {
- case B2400: baud = SPEED_2400; break;
- case B9600: baud = SPEED_9600; break;
- case B19200: baud = SPEED_19200; break;
- case B38400: baud = SPEED_38400; break;
- case B57600: baud = SPEED_57600; break;
- case B115200: baud = SPEED_115200; break;
- case B576000: baud = SPEED_576000; break;
- case B1152000: baud = SPEED_1152000; break;
- case B4000000: baud = SPEED_4000000; break;
+ case B2400: ir_baud = SPEED_2400; break;
default:
- err ("ir-usb driver does not support the baudrate (%d) requested", tty_get_baud_rate(port->tty));
- return;
+ case B9600: ir_baud = SPEED_9600; break;
+ case B19200: ir_baud = SPEED_19200; break;
+ case B38400: ir_baud = SPEED_38400; break;
+ case B57600: ir_baud = SPEED_57600; break;
+ case B115200: ir_baud = SPEED_115200; break;
+ case B576000: ir_baud = SPEED_576000; break;
+ case B1152000: ir_baud = SPEED_1152000; break;
+ case B4000000: ir_baud = SPEED_4000000; break;
}
-
+
+ if (xbof == -1) {
+ ir_xbof = ir_xbof_change(ir_add_bof);
+ } else {
+ ir_xbof = ir_xbof_change(xbof) ;
+ }
+
+ /* Notify the tty driver that the termios have changed. */
+ port->tty->ldisc.set_termios(port->tty, NULL);
+
/* FIXME need to check to see if our write urb is busy right
- * now, or use a urb pool. */
- /* send the baud change out on an "empty" data packet */
+ * now, or use a urb pool.
+ *
+ * send the baud change out on an "empty" data packet
+ */
transfer_buffer = port->write_urb->transfer_buffer;
- transfer_buffer[0] = baud;
- port->write_urb->transfer_buffer_length = 1;
- port->write_urb->dev = port->serial->dev;
+ *transfer_buffer = ir_xbof | ir_baud;
+
+ usb_fill_bulk_urb (
+ port->write_urb,
+ port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer,
+ 1,
+ ir_write_bulk_callback,
+ port);
+
+ port->write_urb->transfer_flags
+ = USB_QUEUE_BULK
+ | USB_ZERO_PACKET;
+
result = usb_submit_urb (port->write_urb);
if (result)
- err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+ err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
}
return;
}
@@ -470,6 +622,8 @@
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
+MODULE_PARM(xbof, "i");
+MODULE_PARM_DESC(xbof, "Force specific number of XBOFs");
MODULE_PARM(buffer_size, "i");
MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers");
diff -u --recursive --new-file pre1/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c
--- pre1/linux/drivers/usb/serial/keyspan.c Sun Jan 6 18:49:21 2002
+++ linux/drivers/usb/serial/keyspan.c Thu Jan 17 14:06:53 2002
@@ -178,15 +178,7 @@
/* Functions used by new usb-serial code. */
static int __init keyspan_init (void)
{
- usb_serial_register (&keyspan_usa18x_pre_device);
- usb_serial_register (&keyspan_usa19_pre_device);
- usb_serial_register (&keyspan_usa19w_pre_device);
- usb_serial_register (&keyspan_usa28_pre_device);
- usb_serial_register (&keyspan_usa28x_pre_device);
- usb_serial_register (&keyspan_usa28xa_pre_device);
- usb_serial_register (&keyspan_usa28xb_pre_device);
- usb_serial_register (&keyspan_usa49w_pre_device);
-
+ usb_serial_register (&keyspan_pre_device);
usb_serial_register (&keyspan_usa18x_device);
usb_serial_register (&keyspan_usa19_device);
usb_serial_register (&keyspan_usa19w_device);
@@ -203,15 +195,7 @@
static void __exit keyspan_exit (void)
{
- usb_serial_deregister (&keyspan_usa18x_pre_device);
- usb_serial_deregister (&keyspan_usa19_pre_device);
- usb_serial_deregister (&keyspan_usa19w_pre_device);
- usb_serial_deregister (&keyspan_usa28_pre_device);
- usb_serial_deregister (&keyspan_usa28x_pre_device);
- usb_serial_deregister (&keyspan_usa28xa_pre_device);
- usb_serial_deregister (&keyspan_usa28xb_pre_device);
- usb_serial_deregister (&keyspan_usa49w_pre_device);
-
+ usb_serial_deregister (&keyspan_pre_device);
usb_serial_deregister (&keyspan_usa18x_device);
usb_serial_deregister (&keyspan_usa19_device);
usb_serial_deregister (&keyspan_usa19w_device);
diff -u --recursive --new-file pre1/linux/drivers/usb/serial/keyspan.h linux/drivers/usb/serial/keyspan.h
--- pre1/linux/drivers/usb/serial/keyspan.h Sun Jan 6 18:49:21 2002
+++ linux/drivers/usb/serial/keyspan.h Thu Jan 17 14:06:53 2002
@@ -372,42 +372,15 @@
ID pattern. But, for now, it looks like we need slightly different
behavior for each match. */
-static __devinitdata struct usb_device_id keyspan_usa18x_pre_ids[] = {
+/* usb_device_id table for the pre-firmware download keyspan devices */
+static __devinitdata struct usb_device_id keyspan_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa19_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa19w_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa28_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa28x_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa28xa_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa28xb_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
- { } /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id keyspan_usa49w_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
{ } /* Terminating entry */
};
@@ -448,10 +421,10 @@
};
/* Structs for the devices, pre and post renumeration. */
-static struct usb_serial_device_type keyspan_usa18x_pre_device = {
+static struct usb_serial_device_type keyspan_pre_device = {
owner: THIS_MODULE,
- name: "Keyspan USA18X - (without firmware)",
- id_table: keyspan_usa18x_pre_ids,
+ name: "Keyspan - (without firmware)",
+ id_table: keyspan_pre_ids,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
@@ -459,84 +432,6 @@
startup: keyspan_fake_startup
};
-static struct usb_serial_device_type keyspan_usa19_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA19 - (without firmware)",
- id_table: keyspan_usa19_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 1,
- startup: keyspan_fake_startup
-};
-
-
-static struct usb_serial_device_type keyspan_usa19w_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA19W - (without firmware)",
- id_table: keyspan_usa19w_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 1,
- startup: keyspan_fake_startup
-};
-
-
-static struct usb_serial_device_type keyspan_usa28_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA28 - (without firmware)",
- id_table: keyspan_usa28_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 2,
- startup: keyspan_fake_startup
-};
-
-static struct usb_serial_device_type keyspan_usa28x_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA28X - (without firmware)",
- id_table: keyspan_usa28x_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 2,
- startup: keyspan_fake_startup
-};
-
-static struct usb_serial_device_type keyspan_usa28xa_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA28XA - (without firmware)",
- id_table: keyspan_usa28xa_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 2,
- startup: keyspan_fake_startup
-};
-
-static struct usb_serial_device_type keyspan_usa28xb_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA28XB - (without firmware)",
- id_table: keyspan_usa28xb_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 2,
- startup: keyspan_fake_startup
-};
-
-static struct usb_serial_device_type keyspan_usa49w_pre_device = {
- owner: THIS_MODULE,
- name: "Keyspan USA49W - (without firmware)",
- id_table: keyspan_usa49w_pre_ids,
- num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
- num_ports: 4,
- startup: keyspan_fake_startup
-};
static struct usb_serial_device_type keyspan_usa18x_device = {
owner: THIS_MODULE,
@@ -550,8 +445,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
- //write_bulk_callback: Not used - we define our own herbs
- //read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -574,8 +467,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
-// write_bulk_callback: keyspan_write_bulk_callback,
-// read_int_callback: keyspan_usa28_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -599,8 +490,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
- //write_bulk_callback: Not used - we define our own herbs
- //read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -640,8 +529,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
-// write_bulk_callback: keyspan_write_bulk_callback,
-// read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -665,8 +552,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
-// write_bulk_callback: keyspan_write_bulk_callback,
-// read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -690,8 +575,6 @@
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
- //write_bulk_callback: Not used - we define our own herbs
- //read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
diff -u --recursive --new-file pre1/linux/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c
--- pre1/linux/drivers/usb/storage/protocol.c Sun Jul 29 21:11:50 2001
+++ linux/drivers/usb/storage/protocol.c Thu Jan 17 14:06:53 2002
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: protocol.c,v 1.10 2001/07/30 00:27:59 mdharm Exp $
+ * $Id: protocol.c,v 1.11 2002/01/13 06:40:25 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -76,7 +76,7 @@
data_ptr = (unsigned char *)srb->request_buffer;
/* Change the SCSI revision number */
- data_ptr[2] |= 0x2;
+ data_ptr[2] = (data_ptr[2] & ~7) | 2;
}
/***********************************************************************
diff -u --recursive --new-file pre1/linux/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h
--- pre1/linux/drivers/usb/storage/unusual_devs.h Mon Jan 14 13:30:20 2002
+++ linux/drivers/usb/storage/unusual_devs.h Thu Jan 17 17:14:09 2002
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Ununsual Devices File
*
- * $Id: unusual_devs.h,v 1.24 2001/12/29 03:12:45 mdharm Exp $
+ * $Id: unusual_devs.h,v 1.25 2002/01/13 06:39:17 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -458,6 +458,14 @@
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
+
+/* Submitted by Brian Hall
+ * Needed for START_STOP flag */
+UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
+ "JMTek",
+ "USBDrive",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ US_FL_START_STOP ),
/* Reported by Dan Pilone
* The device needs the flags only.
diff -u --recursive --new-file pre1/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- pre1/linux/drivers/usb/storage/usb.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/usb/storage/usb.c Thu Jan 17 14:06:53 2002
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.69 2001/11/11 03:33:03 mdharm Exp $
+ * $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -315,6 +315,13 @@
* so get rid of all our resources..
*/
daemonize();
+
+ /* avoid getting signals */
+ spin_lock_irq(¤t->sigmask_lock);
+ flush_signals(current);
+ sigfillset(¤t->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
/* set our name for identification purposes */
sprintf(current->comm, "usb-storage-%d", us->host_number);
diff -u --recursive --new-file pre1/linux/drivers/usb/stv680.c linux/drivers/usb/stv680.c
--- pre1/linux/drivers/usb/stv680.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/usb/stv680.c Thu Jan 17 14:06:53 2002
@@ -43,6 +43,13 @@
* Took out sharpen function, ran code through
* Lindent, and did other minor tweaks to get
* things to work properly with 2.5.1
+ *
+ * ver 0.24 Jan, 2002 (kjs)
+ * Fixed the problem with webcam crashing after
+ * two pictures. Changed the way pic is halved to
+ * improve quality. Got rid of green line around
+ * frame. Fix brightness reset when changing size
+ * bug. Adjusted gamma filters slightly.
*/
#include
@@ -65,7 +72,8 @@
#include "stv680.h"
static int video_nr = -1;
-static int swapRGB = 0;
+static int swapRGB = 0; /* default for auto sleect */
+static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
static unsigned int debug = 0;
@@ -79,7 +87,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.23"
+#define DRIVER_VERSION "v0.24"
#define DRIVER_AUTHOR "Kevin Sisson "
#define DRIVER_DESC "STV0680 USB Camera Driver"
@@ -88,8 +96,8 @@
MODULE_LICENSE ("GPL");
MODULE_PARM (debug, "i");
MODULE_PARM_DESC (debug, "Debug enabled or not");
-MODULE_PARM (swapRGB, "i");
-MODULE_PARM_DESC (swapRGB, "Swap red and blue, e.g., for xawtv");
+MODULE_PARM (swapRGB_on, "i");
+MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
MODULE_PARM (video_nr, "i");
EXPORT_NO_SYMBOLS;
@@ -521,8 +529,15 @@
stv680->palette = STV_VIDEO_PALETTE;
stv680->depth = 24; /* rgb24 bits */
swapRGB = 0;
- PDEBUG (1, "STV(i): swapRGB is OFF");
-
+ if ((swapRGB_on == 0) && (swapRGB == 0))
+ PDEBUG (1, "STV(i): swapRGB is (auto) OFF");
+ else if ((swapRGB_on == 1) && (swapRGB == 1))
+ PDEBUG (1, "STV(i): swapRGB is (auto) ON");
+ else if (swapRGB_on == 1)
+ PDEBUG (1, "STV(i): swapRGB is (forced) ON");
+ else if (swapRGB_on == -1)
+ PDEBUG (1, "STV(i): swapRGB is (forced) OFF");
+
if (stv_set_video_mode (stv680) < 0) {
PDEBUG (0, "STV(e): Could not set video mode in stv_init");
return -1;
@@ -543,6 +558,7 @@
extern struct proc_dir_entry *video_proc_entry;
#define YES_NO(x) ((x) ? "yes" : "no")
+#define ON_OFF(x) ((x) ? "(auto) on" : "(auto) off")
static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
{
@@ -559,7 +575,13 @@
out += sprintf (out, "num_frames : %d\n", STV680_NUMFRAMES);
out += sprintf (out, "Current size : %ix%i\n", stv680->vwidth, stv680->vheight);
- out += sprintf (out, "swapRGB : %s\n", YES_NO (swapRGB));
+ if (swapRGB_on == 0)
+ out += sprintf (out, "swapRGB : %s\n", ON_OFF (swapRGB));
+ else if (swapRGB_on == 1)
+ out += sprintf (out, "swapRGB : (forced) on\n");
+ else if (swapRGB_on == -1)
+ out += sprintf (out, "swapRGB : (forced) off\n");
+
out += sprintf (out, "Palette : %i", stv680->palette);
out += sprintf (out, "\n");
@@ -671,9 +693,7 @@
if (stv680->brightness != p->brightness) {
stv680->chgbright = 1;
stv680->brightness = p->brightness;
- } else {
- stv680->chgbright = 0;
- }
+ }
stv680->whiteness = p->whiteness; /* greyscale */
stv680->colour = p->colour;
@@ -888,7 +908,7 @@
{
int x, y, i;
int w = stv680->cwidth;
- int vw = stv680->cwidth, vh = stv680->cheight, vstep = 1;
+ int vw = stv680->cwidth, vh = stv680->cheight;
unsigned int p = 0;
int colour = 0, bayer = 0;
unsigned char *raw = buffer->data;
@@ -908,46 +928,23 @@
return;
}
- if ((stv680->vwidth == 322) || (stv680->vwidth == 320)) {
+ if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) {
vw = 320;
vh = 240;
- vstep = 1;
}
- if ((stv680->vwidth == 352)) {
+ if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) {
vw = 352;
vh = 288;
- vstep = 1;
}
- if ((stv680->vwidth == 160)) {
- vw = 160;
- vh = 120;
- vstep = 2;
- }
- if ((stv680->vwidth == 176)) {
- vw = 176;
- vh = 144;
- vstep = 2;
- }
- memset (output, 0, 3 * vw * vh); /* clear output matrix. Maybe not necessary. */
+
+ memset (output, 0, 3 * vw * vh); /* clear output matrix. */
for (y = 0; y < vh; y++) {
for (x = 0; x < vw; x++) {
-
- switch (vstep) {
- case 1:
- if (x & 1)
- p = *(raw + y * w + (x >> 1));
- else
- p = *(raw + y * w + (x >> 1) + (w >> 1));
- break;
-
- case 2:
- if (x & 1)
- p = *(raw + ((y * w) << 1) + x);
- else
- p = *(raw + ((y * w) << 1) + x + (w >> 1));
- break;
- }
+ if (x & 1)
+ p = *(raw + y * w + (x >> 1));
+ else
+ p = *(raw + y * w + (x >> 1) + (w >> 1));
if (y & 1)
bayer = 2;
@@ -968,9 +965,10 @@
colour = 2;
break;
}
- i = (y * vw + x) * 3; /* output already zeroed out with memset */
+ i = (y * vw + x) * 3;
*(output + i + colour) = (unsigned char) p;
} /* for x */
+
} /* for y */
/****** gamma correction plus hardcoded white balance */
@@ -979,6 +977,7 @@
(pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1vwidth == 160) || (stv680->vwidth == 176)) {
+ i = 0;
+ for (y = 0; y < vh; y++) {
+ if (!(y & 1)) {
+ for (x = 0; x < vw; x++) {
+ p = (y * vw + x) * 3;
+ if (!(x & 1)) {
+ *(output + i) = *(output + p);
+ *(output + i + 1) = *(output + p + 1);
+ *(output + i + 2) = *(output + p + 2);
+ i += 3;
+ }
+ } /* for x */
+ }
+ } /* for y */
+ }
+ /* reset to proper width */
+ if ((stv680->vwidth == 160)) {
+ vw = 160;
+ vh = 120;
+ }
+ if ((stv680->vwidth == 176)) {
+ vw = 176;
+ vh = 144;
+ }
+
/* output is RGB; some programs want BGR */
- if (swapRGB == 1) {
+ /* swapRGB_on=0 -> program decides; swapRGB_on=1, always swap */
+ /* swapRGB_on=-1, never swap */
+ if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) {
for (y = 0; y < vh; y++) {
for (x = 0; x < vw; x++) {
i = (y * vw + x) * 3;
@@ -1242,7 +1280,7 @@
return -EFAULT;
}
copy_from_user (&p, arg, sizeof (p));
- PDEBUG (2, "STV(i): palette set to RGB in VIDIOSPICT");
+ PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette);
if (stv680_set_pict (stv680, &p))
return -EINVAL;
@@ -1309,8 +1347,8 @@
if (vm.format != STV_VIDEO_PALETTE) {
PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
vm.format, STV_VIDEO_PALETTE);
- if (vm.format == 3) {
- PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is ON");
+ if ((vm.format == 3) && (swapRGB_on == 0)) {
+ PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON");
/* this may fix those apps (e.g., xawtv) that want BGR */
swapRGB = 1;
}
@@ -1320,8 +1358,10 @@
PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
return -EINVAL;
}
- if (stv680->frame[vm.frame].grabstate != FRAME_UNUSED) {
- PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate != FRAME_UNUSED");
+ if ((stv680->frame[vm.frame].grabstate == FRAME_ERROR)
+ || (stv680->frame[vm.frame].grabstate == FRAME_GRABBING)) {
+ PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error",
+ stv680->frame[vm.frame].grabstate);
return -EBUSY;
}
/* Is this according to the v4l spec??? */
diff -u --recursive --new-file pre1/linux/drivers/usb/stv680.h linux/drivers/usb/stv680.h
--- pre1/linux/drivers/usb/stv680.h Thu Jan 3 13:21:28 2002
+++ linux/drivers/usb/stv680.h Thu Jan 17 14:06:53 2002
@@ -43,7 +43,7 @@
#define USB_PENCAM_PRODUCT_ID 0x0202
#define PENCAM_TIMEOUT 1000
/* fmt 4 */
-#define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24
+#define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
@@ -146,77 +146,78 @@
int nullpackets;
};
-unsigned char red[256] = {
- 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
- 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
- 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
- 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
- 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
- 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
- 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
- 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
- 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
- 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
- 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
- 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
- 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
- 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
- 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
- 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
- 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
- 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
- 245, 245, 246, 246
-};
+
+unsigned char red[256] = {
+ 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42,
+ 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69,
+ 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87,
+ 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134,
+ 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143,
+ 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151,
+ 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,
+ 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166,
+ 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173,
+ 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179,
+ 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186,
+ 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192,
+ 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197,
+ 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204,
+ 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209,
+ 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
+ 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219,
+ 220, 220, 221, 221
+};
unsigned char green[256] = {
- 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 32, 39, 45, 50, 54,
- 58, 62, 65, 69, 71, 74, 77, 79, 83, 85, 87, 90,
- 92, 93, 95, 98, 100, 101, 104, 106, 107, 109, 111, 113,
- 114, 116, 118, 119, 121, 122, 124, 126, 127, 128, 129, 132,
- 133, 134, 135, 136, 138, 140, 141, 142, 143, 145, 146, 147,
- 148, 149, 150, 152, 153, 154, 155, 156, 157, 159, 160, 161,
- 162, 163, 164, 166, 167, 168, 168, 169, 170, 171, 173, 174,
- 175, 176, 176, 177, 179, 180, 181, 182, 182, 183, 184, 186,
- 187, 187, 188, 189, 190, 191, 191, 193, 194, 195, 195, 196,
- 197, 198, 198, 200, 201, 201, 202, 203, 204, 204, 205, 207,
- 207, 208, 209, 209, 210, 211, 212, 212, 214, 215, 215, 216,
- 217, 217, 218, 218, 219, 221, 221, 222, 223, 223, 224, 225,
- 225, 226, 226, 228, 229, 229, 230, 231, 231, 232, 232, 233,
- 235, 235, 236, 236, 237, 238, 238, 239, 239, 241, 241, 242,
- 243, 243, 244, 244, 245, 245, 246, 248, 248, 249, 249, 250,
- 250, 251, 251, 252, 253, 253, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255
-};
+ 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
+ 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
+ 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
+ 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
+ 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+ 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
+ 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
+ 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
+ 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
+ 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
+ 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
+ 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
+ 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
+ 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+ 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
+ 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+ 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
+ 245, 245, 246, 246
+};
unsigned char blue[256] = {
- 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 41, 50, 57, 63, 69,
- 74, 78, 82, 87, 90, 94, 97, 100, 105, 108, 111, 113,
- 116, 118, 121, 124, 127, 128, 131, 134, 136, 139, 140, 143,
- 145, 148, 149, 150, 153, 155, 156, 159, 161, 162, 164, 167,
- 168, 170, 171, 173, 174, 177, 179, 180, 182, 183, 185, 186,
- 187, 189, 190, 192, 193, 195, 196, 198, 199, 201, 202, 204,
- 205, 207, 208, 210, 211, 213, 213, 214, 216, 217, 219, 220,
- 222, 223, 223, 224, 226, 227, 229, 230, 230, 232, 233, 235,
- 236, 236, 238, 239, 241, 242, 242, 244, 245, 247, 247, 248,
- 250, 251, 251, 253, 254, 254, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255
-};
+ 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51,
+ 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84,
+ 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106,
+ 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124,
+ 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163,
+ 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174,
+ 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184,
+ 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194,
+ 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203,
+ 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212,
+ 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+ 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235,
+ 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242,
+ 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249,
+ 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+};
diff -u --recursive --new-file pre1/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- pre1/linux/drivers/usb/usb.c Sun Jan 6 18:49:21 2002
+++ linux/drivers/usb/usb.c Thu Jan 17 14:06:53 2002
@@ -2252,6 +2252,14 @@
return -EINVAL;
}
+ /* 9.4.10 says devices don't need this, if the interface
+ only has one alternate setting */
+ if (iface->num_altsetting == 1) {
+ warn("ignoring set_interface for dev %d, iface %d, alt %d",
+ dev->devnum, interface, alternate);
+ return 0;
+ }
+
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
interface, NULL, 0, HZ * 5)) < 0)
diff -u --recursive --new-file pre1/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- pre1/linux/drivers/video/vesafb.c Wed Jan 16 11:16:28 2002
+++ linux/drivers/video/vesafb.c Tue Jan 15 18:47:23 2002
@@ -550,7 +550,7 @@
ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
if (ypan || pmi_setpal) {
- pmi_base = (unsigned short*)isa_bus_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+ pmi_base = (unsigned short*)bus_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
diff -u --recursive --new-file pre1/linux/drivers/zorro/zorro.c linux/drivers/zorro/zorro.c
--- pre1/linux/drivers/zorro/zorro.c Fri Sep 7 09:28:38 2001
+++ linux/drivers/zorro/zorro.c Thu Jan 17 14:21:16 2002
@@ -170,6 +170,7 @@
m68k_memory[i].addr+m68k_memory[i].size, 0);
}
+subsys_initcall(zorro_init);
EXPORT_SYMBOL(zorro_find_device);
EXPORT_SYMBOL(zorro_unused_z2ram);
diff -u --recursive --new-file pre1/linux/fs/Makefile.lib linux/fs/Makefile.lib
--- pre1/linux/fs/Makefile.lib Thu Jan 10 16:23:46 2002
+++ linux/fs/Makefile.lib Tue Jan 15 14:15:53 2002
@@ -1,2 +1,2 @@
-obj-$(CONFIG_FS_JFFS2) += crc32.o
+obj-$(CONFIG_JFFS2_FS) += crc32.o
obj-$(CONFIG_EFI_PARTITION) += crc32.o
diff -u --recursive --new-file pre1/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- pre1/linux/fs/binfmt_misc.c Sat Oct 20 19:14:42 2001
+++ linux/fs/binfmt_misc.c Thu Jan 17 14:25:43 2002
@@ -49,6 +49,8 @@
} Node;
static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
+static struct vfsmount *bm_mnt;
+static int entry_count = 0;
/*
* Check if we support the binfmt
@@ -390,10 +392,15 @@
Node *e = inode->u.generic_ip;
if (e) {
+ struct vfsmount *mnt;
write_lock(&entries_lock);
list_del(&e->list);
+ mnt = bm_mnt;
+ if (!--entry_count)
+ bm_mnt = NULL;
write_unlock(&entries_lock);
kfree(e);
+ mntput(mnt);
}
}
@@ -404,8 +411,7 @@
write_lock(&entries_lock);
dentry = e->dentry;
if (dentry) {
- list_del(&e->list);
- INIT_LIST_HEAD(&e->list);
+ list_del_init(&e->list);
e->dentry = NULL;
}
write_unlock(&entries_lock);
@@ -484,12 +490,16 @@
write: bm_entry_write,
};
+static struct file_system_type bm_fs_type;
+
/* /register */
static ssize_t bm_register_write(struct file *file, const char *buffer,
size_t count, loff_t *ppos)
{
Node *e;
+ struct inode *inode;
+ struct vfsmount *mnt = NULL;
struct dentry *root, *dentry;
struct super_block *sb = file->f_vfsmnt->mnt_sb;
int err = 0;
@@ -503,31 +513,52 @@
down(&root->d_inode->i_sem);
dentry = lookup_one_len(e->name, root, strlen(e->name));
err = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- down(&root->d_inode->i_zombie);
- if (dentry->d_inode) {
- err = -EEXIST;
- } else {
- struct inode * inode = bm_get_inode(sb, S_IFREG | 0644);
- err = -ENOMEM;
+ if (IS_ERR(dentry))
+ goto out;
- if (inode) {
- write_lock(&entries_lock);
+ down(&root->d_inode->i_zombie);
- e->dentry = dget(dentry);
- inode->u.generic_ip = e;
- inode->i_fop = &bm_entry_operations;
- d_instantiate(dentry, inode);
+ err = -EEXIST;
+ if (dentry->d_inode)
+ goto out2;
- list_add(&e->list, &entries);
- write_unlock(&entries_lock);
+ inode = bm_get_inode(sb, S_IFREG | 0644);
- err = 0;
- }
+ err = -ENOMEM;
+ if (!inode)
+ goto out2;
+
+ write_lock(&entries_lock);
+ if (!bm_mnt) {
+ write_unlock(&entries_lock);
+ mnt = kern_mount(&bm_fs_type);
+ if (IS_ERR(mnt)) {
+ err = PTR_ERR(mnt);
+ iput(inode);
+ inode = NULL;
+ goto out2;
}
- up(&root->d_inode->i_zombie);
- dput(dentry);
+ write_lock(&entries_lock);
+ if (!bm_mnt)
+ bm_mnt = mnt;
}
+ mntget(bm_mnt);
+ entry_count++;
+
+ e->dentry = dget(dentry);
+ inode->u.generic_ip = e;
+ inode->i_fop = &bm_entry_operations;
+ d_instantiate(dentry, inode);
+
+ list_add(&e->list, &entries);
+ write_unlock(&entries_lock);
+
+ mntput(mnt);
+ err = 0;
+out2:
+ up(&root->d_inode->i_zombie);
+ dput(dentry);
+out:
up(&root->d_inode->i_sem);
dput(root);
@@ -687,23 +718,13 @@
static DECLARE_FSTYPE(bm_fs_type, "binfmt_misc", bm_read_super, FS_SINGLE|FS_LITTER);
-static struct vfsmount *bm_mnt;
-
static int __init init_misc_binfmt(void)
{
int err = register_filesystem(&bm_fs_type);
if (!err) {
- bm_mnt = kern_mount(&bm_fs_type);
- err = PTR_ERR(bm_mnt);
- if (IS_ERR(bm_mnt))
+ err = register_binfmt(&misc_format);
+ if (err)
unregister_filesystem(&bm_fs_type);
- else {
- err = register_binfmt(&misc_format);
- if (err) {
- unregister_filesystem(&bm_fs_type);
- kern_umount(bm_mnt);
- }
- }
}
return err;
}
@@ -712,7 +733,6 @@
{
unregister_binfmt(&misc_format);
unregister_filesystem(&bm_fs_type);
- kern_umount(bm_mnt);
}
EXPORT_NO_SYMBOLS;
diff -u --recursive --new-file pre1/linux/fs/buffer.c linux/fs/buffer.c
--- pre1/linux/fs/buffer.c Mon Jan 14 09:38:37 2002
+++ linux/fs/buffer.c Thu Jan 17 14:29:59 2002
@@ -582,23 +582,13 @@
return bh;
}
-void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
+void buffer_insert_list(struct buffer_head *bh, struct list_head *list)
{
spin_lock(&lru_list_lock);
if (bh->b_inode)
list_del(&bh->b_inode_buffers);
- bh->b_inode = inode;
- list_add(&bh->b_inode_buffers, &inode->i_dirty_buffers);
- spin_unlock(&lru_list_lock);
-}
-
-void buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode)
-{
- spin_lock(&lru_list_lock);
- if (bh->b_inode)
- list_del(&bh->b_inode_buffers);
- bh->b_inode = inode;
- list_add(&bh->b_inode_buffers, &inode->i_dirty_data_buffers);
+ bh->b_inode = 1;
+ list_add(&bh->b_inode_buffers, list);
spin_unlock(&lru_list_lock);
}
@@ -606,7 +596,7 @@
remove_inode_queue functions. */
static void __remove_inode_queue(struct buffer_head *bh)
{
- bh->b_inode = NULL;
+ bh->b_inode = 0;
list_del(&bh->b_inode_buffers);
}
@@ -826,73 +816,24 @@
* any newly dirty buffers for write.
*/
-int fsync_inode_buffers(struct inode *inode)
-{
- struct buffer_head *bh;
- struct inode tmp;
- int err = 0, err2;
-
- INIT_LIST_HEAD(&tmp.i_dirty_buffers);
-
- spin_lock(&lru_list_lock);
-
- while (!list_empty(&inode->i_dirty_buffers)) {
- bh = BH_ENTRY(inode->i_dirty_buffers.next);
- list_del(&bh->b_inode_buffers);
- if (!buffer_dirty(bh) && !buffer_locked(bh))
- bh->b_inode = NULL;
- else {
- bh->b_inode = &tmp;
- list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
- if (buffer_dirty(bh)) {
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- ll_rw_block(WRITE, 1, &bh);
- brelse(bh);
- spin_lock(&lru_list_lock);
- }
- }
- }
-
- while (!list_empty(&tmp.i_dirty_buffers)) {
- bh = BH_ENTRY(tmp.i_dirty_buffers.prev);
- remove_inode_queue(bh);
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- err = -EIO;
- brelse(bh);
- spin_lock(&lru_list_lock);
- }
-
- spin_unlock(&lru_list_lock);
- err2 = osync_inode_buffers(inode);
-
- if (err)
- return err;
- else
- return err2;
-}
-
-int fsync_inode_data_buffers(struct inode *inode)
+int fsync_buffers_list(struct list_head *list)
{
struct buffer_head *bh;
- struct inode tmp;
+ struct list_head tmp;
int err = 0, err2;
- INIT_LIST_HEAD(&tmp.i_dirty_data_buffers);
+ INIT_LIST_HEAD(&tmp);
spin_lock(&lru_list_lock);
- while (!list_empty(&inode->i_dirty_data_buffers)) {
- bh = BH_ENTRY(inode->i_dirty_data_buffers.next);
+ while (!list_empty(list)) {
+ bh = BH_ENTRY(list->next);
list_del(&bh->b_inode_buffers);
if (!buffer_dirty(bh) && !buffer_locked(bh))
- bh->b_inode = NULL;
+ bh->b_inode = 0;
else {
- bh->b_inode = &tmp;
- list_add(&bh->b_inode_buffers, &tmp.i_dirty_data_buffers);
+ bh->b_inode = 1;
+ list_add(&bh->b_inode_buffers, &tmp);
if (buffer_dirty(bh)) {
get_bh(bh);
spin_unlock(&lru_list_lock);
@@ -903,8 +844,8 @@
}
}
- while (!list_empty(&tmp.i_dirty_data_buffers)) {
- bh = BH_ENTRY(tmp.i_dirty_data_buffers.prev);
+ while (!list_empty(&tmp)) {
+ bh = BH_ENTRY(tmp.prev);
remove_inode_queue(bh);
get_bh(bh);
spin_unlock(&lru_list_lock);
@@ -916,7 +857,7 @@
}
spin_unlock(&lru_list_lock);
- err2 = osync_inode_data_buffers(inode);
+ err2 = osync_buffers_list(list);
if (err)
return err;
@@ -935,19 +876,19 @@
* write will not be flushed to disk by the osync.
*/
-int osync_inode_buffers(struct inode *inode)
+int osync_buffers_list(struct list_head *list)
{
struct buffer_head *bh;
- struct list_head *list;
+ struct list_head *p;
int err = 0;
spin_lock(&lru_list_lock);
repeat:
- for (list = inode->i_dirty_buffers.prev;
- bh = BH_ENTRY(list), list != &inode->i_dirty_buffers;
- list = bh->b_inode_buffers.prev) {
+ for (p = list->prev;
+ bh = BH_ENTRY(p), p != list;
+ p = bh->b_inode_buffers.prev) {
if (buffer_locked(bh)) {
get_bh(bh);
spin_unlock(&lru_list_lock);
@@ -963,36 +904,6 @@
spin_unlock(&lru_list_lock);
return err;
}
-
-int osync_inode_data_buffers(struct inode *inode)
-{
- struct buffer_head *bh;
- struct list_head *list;
- int err = 0;
-
- spin_lock(&lru_list_lock);
-
- repeat:
-
- for (list = inode->i_dirty_data_buffers.prev;
- bh = BH_ENTRY(list), list != &inode->i_dirty_data_buffers;
- list = bh->b_inode_buffers.prev) {
- if (buffer_locked(bh)) {
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- err = -EIO;
- brelse(bh);
- spin_lock(&lru_list_lock);
- goto repeat;
- }
- }
-
- spin_unlock(&lru_list_lock);
- return err;
-}
-
/*
* Invalidate any and all dirty buffers on a given inode. We are
diff -u --recursive --new-file pre1/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- pre1/linux/fs/ext2/balloc.c Sun Dec 16 12:23:00 2001
+++ linux/fs/ext2/balloc.c Thu Jan 17 14:24:50 2002
@@ -42,19 +42,20 @@
unsigned long group_desc;
unsigned long desc;
struct ext2_group_desc * gdp;
+ struct ext2_sb_info *sbi = &sb->u.ext2_sb;
- if (block_group >= sb->u.ext2_sb.s_groups_count) {
+ if (block_group >= sbi->s_groups_count) {
ext2_error (sb, "ext2_get_group_desc",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, sb->u.ext2_sb.s_groups_count);
+ block_group, sbi->s_groups_count);
return NULL;
}
group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
desc = block_group % EXT2_DESC_PER_BLOCK(sb);
- if (!sb->u.ext2_sb.s_group_desc[group_desc]) {
+ if (!sbi->s_group_desc[group_desc]) {
ext2_error (sb, "ext2_get_group_desc",
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
@@ -62,10 +63,9 @@
return NULL;
}
- gdp = (struct ext2_group_desc *)
- sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
+ gdp = (struct ext2_group_desc *) sbi->s_group_desc[group_desc]->b_data;
if (bh)
- *bh = sb->u.ext2_sb.s_group_desc[group_desc];
+ *bh = sbi->s_group_desc[group_desc];
return gdp + desc;
}
@@ -73,37 +73,26 @@
* Read the bitmap for a given block_group, reading into the specified
* slot in the superblock's bitmap cache.
*
- * Return >=0 on success or a -ve error code.
+ * Return buffer_head on success or NULL in case of failure.
*/
-static int read_block_bitmap (struct super_block * sb,
- unsigned int block_group,
- unsigned long bitmap_nr)
+static struct buffer_head *read_block_bitmap(struct super_block *sb,
+ unsigned int block_group)
{
struct ext2_group_desc * gdp;
struct buffer_head * bh = NULL;
- int retval = -EIO;
gdp = ext2_get_group_desc (sb, block_group, NULL);
if (!gdp)
goto error_out;
- retval = 0;
bh = sb_bread(sb, le32_to_cpu(gdp->bg_block_bitmap));
- if (!bh) {
+ if (!bh)
ext2_error (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %lu",
block_group, (unsigned long) gdp->bg_block_bitmap);
- retval = -EIO;
- }
- /*
- * On IO error, just leave a zero in the superblock's block pointer for
- * this group. The IO will be retried next time.
- */
error_out:
- sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
- sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
- return retval;
+ return bh;
}
/*
@@ -117,134 +106,65 @@
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*
- * Return the slot used to store the bitmap, or a -ve error code.
+ * Return the buffer_head of the bitmap or ERR_PTR(-ve).
*/
-static int __load_block_bitmap (struct super_block * sb,
- unsigned int block_group)
+static struct buffer_head *load_block_bitmap(struct super_block * sb,
+ unsigned int block_group)
{
- int i, j, retval = 0;
- unsigned long block_bitmap_number;
- struct buffer_head * block_bitmap;
+ struct ext2_sb_info *sbi = &sb->u.ext2_sb;
+ int i, slot = 0;
+ struct buffer_head *bh = sbi->s_block_bitmap[0];
- if (block_group >= sb->u.ext2_sb.s_groups_count)
+ if (block_group >= sbi->s_groups_count)
ext2_panic (sb, "load_block_bitmap",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, sb->u.ext2_sb.s_groups_count);
-
- if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
- if (sb->u.ext2_sb.s_block_bitmap[block_group]) {
- if (sb->u.ext2_sb.s_block_bitmap_number[block_group] ==
- block_group)
- return block_group;
- ext2_error (sb, "__load_block_bitmap",
- "block_group != block_bitmap_number");
- }
- retval = read_block_bitmap (sb, block_group, block_group);
- if (retval < 0)
- return retval;
- return block_group;
- }
-
- for (i = 0; i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
- sb->u.ext2_sb.s_block_bitmap_number[i] != block_group; i++)
- ;
- if (i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
- sb->u.ext2_sb.s_block_bitmap_number[i] == block_group) {
- block_bitmap_number = sb->u.ext2_sb.s_block_bitmap_number[i];
- block_bitmap = sb->u.ext2_sb.s_block_bitmap[i];
- for (j = i; j > 0; j--) {
- sb->u.ext2_sb.s_block_bitmap_number[j] =
- sb->u.ext2_sb.s_block_bitmap_number[j - 1];
- sb->u.ext2_sb.s_block_bitmap[j] =
- sb->u.ext2_sb.s_block_bitmap[j - 1];
- }
- sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
- sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
-
- /*
- * There's still one special case here --- if block_bitmap == 0
- * then our last attempt to read the bitmap failed and we have
- * just ended up caching that failure. Try again to read it.
- */
- if (!block_bitmap)
- retval = read_block_bitmap (sb, block_group, 0);
- } else {
- if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
- sb->u.ext2_sb.s_loaded_block_bitmaps++;
- else
- brelse (sb->u.ext2_sb.s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
- for (j = sb->u.ext2_sb.s_loaded_block_bitmaps - 1; j > 0; j--) {
- sb->u.ext2_sb.s_block_bitmap_number[j] =
- sb->u.ext2_sb.s_block_bitmap_number[j - 1];
- sb->u.ext2_sb.s_block_bitmap[j] =
- sb->u.ext2_sb.s_block_bitmap[j - 1];
- }
- retval = read_block_bitmap (sb, block_group, 0);
- }
- return retval;
-}
-
-/*
- * Load the block bitmap for a given block group. First of all do a couple
- * of fast lookups for common cases and then pass the request onto the guts
- * of the bitmap loader.
- *
- * Return the slot number of the group in the superblock bitmap cache's on
- * success, or a -ve error code.
- *
- * There is still one inconsistency here --- if the number of groups in this
- * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of
- * differentiating between a group for which we have never performed a bitmap
- * IO request, and a group for which the last bitmap read request failed.
- */
-static inline int load_block_bitmap (struct super_block * sb,
- unsigned int block_group)
-{
- int slot;
+ block_group, sbi->s_groups_count);
/*
* Do the lookup for the slot. First of all, check if we're asking
* for the same slot as last time, and did we succeed that last time?
*/
- if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
- sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
- sb->u.ext2_sb.s_block_bitmap[0]) {
- return 0;
- }
- /*
- * Or can we do a fast lookup based on a loaded group on a filesystem
- * small enough to be mapped directly into the superblock?
- */
- else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED &&
- sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
- sb->u.ext2_sb.s_block_bitmap[block_group]) {
+ if (sbi->s_loaded_block_bitmaps > 0 &&
+ sbi->s_block_bitmap_number[0] == block_group && bh)
+ goto found;
+
+ if (sbi->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
slot = block_group;
- }
- /*
- * If not, then do a full lookup for this block group.
- */
- else {
- slot = __load_block_bitmap (sb, block_group);
+ bh = sbi->s_block_bitmap[slot];
+ if (!bh)
+ goto read_it;
+ if (sbi->s_block_bitmap_number[slot] == slot)
+ goto found;
+ ext2_panic (sb, "__load_block_bitmap",
+ "block_group != block_bitmap_number");
}
- /*
- * <0 means we just got an error
- */
- if (slot < 0)
- return slot;
-
- /*
- * If it's a valid slot, we may still have cached a previous IO error,
- * in which case the bh in the superblock cache will be zero.
- */
- if (!sb->u.ext2_sb.s_block_bitmap[slot])
- return -EIO;
-
- /*
- * Must have been read in OK to get this far.
- */
- return slot;
+ bh = NULL;
+ for (i = 0; i < sbi->s_loaded_block_bitmaps &&
+ sbi->s_block_bitmap_number[i] != block_group; i++)
+ ;
+ if (i < sbi->s_loaded_block_bitmaps)
+ bh = sbi->s_block_bitmap[i];
+ else if (sbi->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
+ sbi->s_loaded_block_bitmaps++;
+ else
+ brelse (sbi->s_block_bitmap[--i]);
+
+ while (i--) {
+ sbi->s_block_bitmap_number[i+1] = sbi->s_block_bitmap_number[i];
+ sbi->s_block_bitmap[i+1] = sbi->s_block_bitmap[i];
+ }
+
+read_it:
+ if (!bh)
+ bh = read_block_bitmap(sb, block_group);
+ sbi->s_block_bitmap_number[slot] = block_group;
+ sbi->s_block_bitmap[slot] = bh;
+ if (!bh)
+ return ERR_PTR(-EIO);
+found:
+ return bh;
}
/* Free given blocks, update quota and i_blocks field */
@@ -256,7 +176,6 @@
unsigned long block_group;
unsigned long bit;
unsigned long i;
- int bitmap_nr;
unsigned long overflow;
struct super_block * sb;
struct ext2_group_desc * gdp;
@@ -293,11 +212,10 @@
overflow = bit + count - EXT2_BLOCKS_PER_GROUP(sb);
count -= overflow;
}
- bitmap_nr = load_block_bitmap (sb, block_group);
- if (bitmap_nr < 0)
+ bh = load_block_bitmap (sb, block_group);
+ if (IS_ERR(bh))
goto error_return;
- bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
gdp = ext2_get_group_desc (sb, block_group, &bh2);
if (!gdp)
goto error_return;
@@ -361,7 +279,6 @@
struct buffer_head * bh2;
char * p, * r;
int i, j, k, tmp;
- int bitmap_nr;
struct super_block * sb;
struct ext2_group_desc * gdp;
struct ext2_super_block * es;
@@ -404,12 +321,10 @@
if (j)
goal_attempts++;
#endif
- bitmap_nr = load_block_bitmap (sb, i);
- if (bitmap_nr < 0)
+ bh = load_block_bitmap (sb, i);
+ if (IS_ERR(bh))
goto io_error;
- bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
-
ext2_debug ("goal is at %d:%d.\n", i, j);
if (!ext2_test_bit(j, bh->b_data)) {
@@ -477,11 +392,10 @@
}
if (k >= sb->u.ext2_sb.s_groups_count)
goto out;
- bitmap_nr = load_block_bitmap (sb, i);
- if (bitmap_nr < 0)
+ bh = load_block_bitmap (sb, i);
+ if (IS_ERR(bh))
goto io_error;
- bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
j = (r - bh->b_data) << 3;
if (j < EXT2_BLOCKS_PER_GROUP(sb))
@@ -619,7 +533,6 @@
#ifdef EXT2FS_DEBUG
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
- int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
@@ -629,16 +542,16 @@
bitmap_count = 0;
gdp = NULL;
for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
+ struct buffer_head *bh;
gdp = ext2_get_group_desc (sb, i, NULL);
if (!gdp)
continue;
desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
- bitmap_nr = load_block_bitmap (sb, i);
- if (bitmap_nr < 0)
+ bh = load_block_bitmap (sb, i);
+ if (IS_ERR(bh))
continue;
- x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
- sb->s_blocksize);
+ x = ext2_count_free (bh, sb->s_blocksize);
printk ("group %d: stored = %d, counted = %lu\n",
i, le16_to_cpu(gdp->bg_free_blocks_count), x);
bitmap_count += x;
@@ -720,7 +633,6 @@
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x, j;
unsigned long desc_blocks;
- int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
@@ -733,11 +645,9 @@
if (!gdp)
continue;
desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
- bitmap_nr = load_block_bitmap (sb, i);
- if (bitmap_nr < 0)
+ bh = load_block_bitmap (sb, i);
+ if (IS_ERR(bh))
continue;
-
- bh = EXT2_SB(sb)->s_block_bitmap[bitmap_nr];
if (ext2_bg_has_super(sb, i) && !ext2_test_bit(0, bh->b_data))
ext2_error(sb, __FUNCTION__,
diff -u --recursive --new-file pre1/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- pre1/linux/fs/fat/inode.c Wed Jan 16 11:16:28 2002
+++ linux/fs/fat/inode.c Wed Jan 16 10:20:23 2002
@@ -559,9 +559,9 @@
struct buffer_head *bh;
struct fat_boot_sector *b;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
- int logical_sector_size, fat_clusters;
+ int logical_sector_size, fat_clusters, debug, cp;
unsigned int total_sectors, rootdir_sectors;
- int debug, cp;
+ long error = -EIO;
char buf[50];
int i;
char cvf_format[21];
@@ -786,9 +786,8 @@
return sb;
out_invalid:
- if (!silent)
- printk("VFS: Can't find a valid FAT filesystem on dev %s.\n",
- sb->s_id);
+ error = 0;
+
out_fail:
if (sbi->nls_io)
unload_nls(sbi->nls_io);
@@ -799,8 +798,8 @@
if (sbi->private_data)
kfree(sbi->private_data);
sbi->private_data = NULL;
-
- return NULL;
+
+ return ERR_PTR(error);
}
int fat_statfs(struct super_block *sb,struct statfs *buf)
diff -u --recursive --new-file pre1/linux/fs/inode.c linux/fs/inode.c
--- pre1/linux/fs/inode.c Mon Jan 14 10:10:43 2002
+++ linux/fs/inode.c Thu Jan 17 14:30:00 2002
@@ -75,13 +75,53 @@
static kmem_cache_t * inode_cachep;
-#define alloc_inode() \
- ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))
+static struct inode *alloc_inode(struct super_block *sb)
+{
+ static struct address_space_operations empty_aops;
+ static struct inode_operations empty_iops;
+ static struct file_operations empty_fops;
+ struct inode *inode;
+
+ if (sb->s_op->alloc_inode)
+ inode = sb->s_op->alloc_inode(sb);
+ else
+ inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
+
+ if (inode) {
+ inode->i_sb = sb;
+ inode->i_dev = sb->s_dev;
+ inode->i_blkbits = sb->s_blocksize_bits;
+ inode->i_flags = 0;
+ atomic_set(&inode->i_count, 1);
+ inode->i_sock = 0;
+ inode->i_op = &empty_iops;
+ inode->i_fop = &empty_fops;
+ inode->i_nlink = 1;
+ atomic_set(&inode->i_writecount, 0);
+ inode->i_size = 0;
+ inode->i_blocks = 0;
+ inode->i_generation = 0;
+ memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
+ inode->i_pipe = NULL;
+ inode->i_bdev = NULL;
+ inode->i_cdev = NULL;
+ inode->i_data.a_ops = &empty_aops;
+ inode->i_data.host = inode;
+ inode->i_data.gfp_mask = GFP_HIGHUSER;
+ inode->i_mapping = &inode->i_data;
+ memset(&inode->u, 0, sizeof(inode->u));
+ }
+ return inode;
+}
+
static void destroy_inode(struct inode *inode)
{
if (inode_has_buffers(inode))
BUG();
- kmem_cache_free(inode_cachep, (inode));
+ if (inode->i_sb->s_op->destroy_inode)
+ inode->i_sb->s_op->destroy_inode(inode);
+ else
+ kmem_cache_free(inode_cachep, (inode));
}
@@ -90,27 +130,30 @@
* once, because the fields are idempotent across use
* of the inode, so let the slab aware of that.
*/
+void inode_init_once(struct inode *inode)
+{
+ memset(inode, 0, sizeof(*inode));
+ init_waitqueue_head(&inode->i_wait);
+ INIT_LIST_HEAD(&inode->i_hash);
+ INIT_LIST_HEAD(&inode->i_data.clean_pages);
+ INIT_LIST_HEAD(&inode->i_data.dirty_pages);
+ INIT_LIST_HEAD(&inode->i_data.locked_pages);
+ INIT_LIST_HEAD(&inode->i_dentry);
+ INIT_LIST_HEAD(&inode->i_dirty_buffers);
+ INIT_LIST_HEAD(&inode->i_dirty_data_buffers);
+ INIT_LIST_HEAD(&inode->i_devices);
+ sema_init(&inode->i_sem, 1);
+ sema_init(&inode->i_zombie, 1);
+ spin_lock_init(&inode->i_data.i_shared_lock);
+}
+
static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
{
struct inode * inode = (struct inode *) foo;
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR)
- {
- memset(inode, 0, sizeof(*inode));
- init_waitqueue_head(&inode->i_wait);
- INIT_LIST_HEAD(&inode->i_hash);
- INIT_LIST_HEAD(&inode->i_data.clean_pages);
- INIT_LIST_HEAD(&inode->i_data.dirty_pages);
- INIT_LIST_HEAD(&inode->i_data.locked_pages);
- INIT_LIST_HEAD(&inode->i_dentry);
- INIT_LIST_HEAD(&inode->i_dirty_buffers);
- INIT_LIST_HEAD(&inode->i_dirty_data_buffers);
- INIT_LIST_HEAD(&inode->i_devices);
- sema_init(&inode->i_sem, 1);
- sema_init(&inode->i_zombie, 1);
- spin_lock_init(&inode->i_data.i_shared_lock);
- }
+ inode_init_once(inode);
}
/*
@@ -768,72 +811,28 @@
return inode;
}
-/*
- * This just initializes the inode fields
- * to known values before returning the inode..
- *
- * i_sb, i_ino, i_count, i_state and the lists have
- * been initialized elsewhere..
- */
-static void clean_inode(struct inode *inode)
-{
- static struct address_space_operations empty_aops;
- static struct inode_operations empty_iops;
- static struct file_operations empty_fops;
- memset(&inode->u, 0, sizeof(inode->u));
- inode->i_sock = 0;
- inode->i_op = &empty_iops;
- inode->i_fop = &empty_fops;
- inode->i_nlink = 1;
- atomic_set(&inode->i_writecount, 0);
- inode->i_size = 0;
- inode->i_blocks = 0;
- inode->i_generation = 0;
- memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
- inode->i_pipe = NULL;
- inode->i_bdev = NULL;
- inode->i_cdev = NULL;
- inode->i_data.a_ops = &empty_aops;
- inode->i_data.host = inode;
- inode->i_data.gfp_mask = GFP_HIGHUSER;
- inode->i_mapping = &inode->i_data;
-}
-
/**
- * get_empty_inode - obtain an inode
+ * new_inode - obtain an inode
+ * @sb: superblock
*
- * This is called by things like the networking layer
- * etc that want to get an inode without any inode
- * number, or filesystems that allocate new inodes with
- * no pre-existing information.
- *
- * On a successful return the inode pointer is returned. On a failure
- * a %NULL pointer is returned. The returned inode is not on any superblock
- * lists.
+ * Allocates a new inode for given superblock.
*/
-struct inode * get_empty_inode(void)
+struct inode *new_inode(struct super_block *sb)
{
static unsigned long last_ino;
struct inode * inode;
spin_lock_prefetch(&inode_lock);
- inode = alloc_inode();
- if (inode)
- {
+ inode = alloc_inode(sb);
+ if (inode) {
spin_lock(&inode_lock);
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
- inode->i_sb = NULL;
- inode->i_dev = NODEV;
- inode->i_blkbits = 0;
inode->i_ino = ++last_ino;
- inode->i_flags = 0;
- atomic_set(&inode->i_count, 1);
inode->i_state = 0;
spin_unlock(&inode_lock);
- clean_inode(inode);
}
return inode;
}
@@ -848,7 +847,7 @@
{
struct inode * inode;
- inode = alloc_inode();
+ inode = alloc_inode(sb);
if (inode) {
struct inode * old;
@@ -859,16 +858,9 @@
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
- inode->i_sb = sb;
- inode->i_dev = sb->s_dev;
- inode->i_blkbits = sb->s_blocksize_bits;
inode->i_ino = ino;
- inode->i_flags = 0;
- atomic_set(&inode->i_count, 1);
inode->i_state = I_LOCK;
spin_unlock(&inode_lock);
-
- clean_inode(inode);
/* reiserfs specific hack right here. We don't
** want this to last, and are looking for VFS changes
diff -u --recursive --new-file pre1/linux/fs/intermezzo/kml_reint.c linux/fs/intermezzo/kml_reint.c
--- pre1/linux/fs/intermezzo/kml_reint.c Sun Nov 11 10:20:21 2001
+++ linux/fs/intermezzo/kml_reint.c Tue Jan 15 14:33:55 2002
@@ -17,7 +17,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff -u --recursive --new-file pre1/linux/fs/jbd/commit.c linux/fs/jbd/commit.c
--- pre1/linux/fs/jbd/commit.c Sun Dec 30 16:59:00 2001
+++ linux/fs/jbd/commit.c Tue Jan 15 13:53:51 2002
@@ -224,14 +224,13 @@
}
} while (jh != last_jh);
- if (bufs || current->need_resched) {
+ if (bufs || need_resched()) {
jbd_debug(2, "submit %d writes\n", bufs);
spin_unlock(&journal_datalist_lock);
unlock_journal(journal);
if (bufs)
ll_rw_block(WRITE, bufs, wbuf);
- if (current->need_resched)
- schedule();
+ cond_resched();
journal_brelse_array(wbuf, bufs);
lock_journal(journal);
spin_lock(&journal_datalist_lock);
@@ -458,8 +457,7 @@
bh->b_end_io = journal_end_buffer_io_sync;
submit_bh(WRITE, bh);
}
- if (current->need_resched)
- schedule();
+ cond_resched();
lock_journal(journal);
/* Force a new descriptor to be generated next
diff -u --recursive --new-file pre1/linux/fs/jffs2/background.c linux/fs/jffs2/background.c
--- pre1/linux/fs/jffs2/background.c Mon Jan 7 12:55:16 2002
+++ linux/fs/jffs2/background.c Tue Jan 15 13:53:51 2002
@@ -127,8 +127,7 @@
schedule();
}
- if (current->need_resched)
- schedule();
+ cond_resched();
/* Put_super will send a SIGKILL and then wait on the sem.
*/
diff -u --recursive --new-file pre1/linux/fs/jffs2/erase.c linux/fs/jffs2/erase.c
--- pre1/linux/fs/jffs2/erase.c Thu Jan 10 16:23:46 2002
+++ linux/fs/jffs2/erase.c Tue Jan 15 13:53:51 2002
@@ -131,8 +131,7 @@
jffs2_erase_block(c, jeb);
/* Be nice */
- if (current->need_resched)
- schedule();
+ cond_resched();
spin_lock_bh(&c->erase_completion_lock);
}
spin_unlock_bh(&c->erase_completion_lock);
diff -u --recursive --new-file pre1/linux/fs/jffs2/nodemgmt.c linux/fs/jffs2/nodemgmt.c
--- pre1/linux/fs/jffs2/nodemgmt.c Thu Oct 4 15:13:18 2001
+++ linux/fs/jffs2/nodemgmt.c Tue Jan 15 13:53:51 2002
@@ -101,8 +101,7 @@
if (ret)
return ret;
- if (current->need_resched)
- schedule();
+ cond_resched();
if (signal_pending(current))
return -EINTR;
diff -u --recursive --new-file pre1/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- pre1/linux/fs/msdos/msdosfs_syms.c Sun Dec 30 16:58:58 2001
+++ linux/fs/msdos/msdosfs_syms.c Wed Jan 16 10:20:23 2002
@@ -23,7 +23,6 @@
EXPORT_SYMBOL(msdos_rename);
EXPORT_SYMBOL(msdos_rmdir);
EXPORT_SYMBOL(msdos_unlink);
-EXPORT_SYMBOL(msdos_read_super);
EXPORT_SYMBOL(msdos_put_super);
static DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
diff -u --recursive --new-file pre1/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- pre1/linux/fs/msdos/namei.c Sun Dec 30 10:53:53 2001
+++ linux/fs/msdos/namei.c Wed Jan 16 10:20:23 2002
@@ -589,7 +589,15 @@
MSDOS_SB(sb)->options.isvfat = 0;
res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
- if (res)
- sb->s_root->d_op = &msdos_dentry_operations;
+ if (IS_ERR(res))
+ return NULL;
+ if (res == NULL) {
+ if (!silent)
+ printk(KERN_INFO "VFS: Can't find a valid"
+ " MSDOS filesystem on dev %s.\n", sb->s_id);
+ return NULL;
+ }
+
+ sb->s_root->d_op = &msdos_dentry_operations;
return res;
}
diff -u --recursive --new-file pre1/linux/fs/namei.c linux/fs/namei.c
--- pre1/linux/fs/namei.c Mon Jan 14 09:41:57 2002
+++ linux/fs/namei.c Tue Jan 15 13:53:51 2002
@@ -339,7 +339,7 @@
goto loop;
if (current->total_link_count >= 40)
goto loop;
- if (current->need_resched) {
+ if (need_resched()) {
current->state = TASK_RUNNING;
schedule();
}
diff -u --recursive --new-file pre1/linux/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- pre1/linux/fs/reiserfs/inode.c Fri Jan 4 09:42:12 2002
+++ linux/fs/reiserfs/inode.c Thu Jan 17 14:29:59 2002
@@ -101,9 +101,9 @@
}
static void add_to_flushlist(struct inode *inode, struct buffer_head *bh) {
- struct inode *jinode = &(SB_JOURNAL(inode->i_sb)->j_dummy_inode) ;
+ struct list_head *list = &(SB_JOURNAL(inode->i_sb)->j_dirty_buffers) ;
- buffer_insert_inode_queue(bh, jinode) ;
+ buffer_insert_list(bh, list) ;
}
//
@@ -808,8 +808,7 @@
/* inserting indirect pointers for a hole can take a
** long time. reschedule if needed
*/
- if (current->need_resched)
- schedule() ;
+ cond_resched();
retval = search_for_position_by_key (inode->i_sb, &key, &path);
if (retval == IO_ERROR) {
diff -u --recursive --new-file pre1/linux/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c
--- pre1/linux/fs/reiserfs/journal.c Mon Jan 14 09:38:46 2002
+++ linux/fs/reiserfs/journal.c Thu Jan 17 14:29:59 2002
@@ -1897,7 +1897,7 @@
memset(journal_writers, 0, sizeof(char *) * 512) ; /* debug code */
INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ;
- INIT_LIST_HEAD(&(SB_JOURNAL(p_s_sb)->j_dummy_inode.i_dirty_buffers)) ;
+ INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_dirty_buffers) ;
reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap,
SB_BMAP_NR(p_s_sb)) ;
allocate_bitmap_nodes(p_s_sb) ;
@@ -2902,7 +2902,7 @@
SB_JOURNAL_LIST_INDEX(p_s_sb) = jindex ;
/* write any buffers that must hit disk before this commit is done */
- fsync_inode_buffers(&(SB_JOURNAL(p_s_sb)->j_dummy_inode)) ;
+ fsync_buffers_list(&(SB_JOURNAL(p_s_sb)->j_dirty_buffers)) ;
/* honor the flush and async wishes from the caller */
if (flush) {
diff -u --recursive --new-file pre1/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- pre1/linux/fs/umsdos/inode.c Tue Jan 1 18:55:00 2002
+++ linux/fs/umsdos/inode.c Wed Jan 16 10:20:23 2002
@@ -363,10 +363,17 @@
* Call msdos-fs to mount the disk.
* Note: this returns res == sb or NULL
*/
- res = msdos_read_super (sb, data, silent);
+ MSDOS_SB(sb)->options.isvfat = 0;
+ res = fat_read_super(sb, data, silent, &umsdos_rdir_inode_operations);
- if (!res)
- goto out_fail;
+ if (IS_ERR(res))
+ return NULL;
+ if (res == NULL) {
+ if (!silent)
+ printk(KERN_INFO "VFS: Can't find a valid "
+ "UMSDOS filesystem on dev %s.\n", sb->s_id);
+ return NULL;
+ }
printk (KERN_INFO "UMSDOS 0.86k "
"(compatibility level %d.%d, fast msdos)\n",
@@ -394,10 +401,6 @@
dget (sb->s_root); sb->s_root = dget(new_root);
}
return sb;
-
-out_fail:
- printk(KERN_INFO "UMSDOS: msdos_read_super failed, mount aborted.\n");
- return NULL;
}
/*
diff -u --recursive --new-file pre1/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- pre1/linux/fs/vfat/namei.c Wed Jan 16 11:16:28 2002
+++ linux/fs/vfat/namei.c Wed Jan 16 10:20:23 2002
@@ -1266,10 +1266,15 @@
struct super_block *res;
MSDOS_SB(sb)->options.isvfat = 1;
-
res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
- if (res == NULL)
+ if (IS_ERR(res))
return NULL;
+ if (res == NULL) {
+ if (!silent)
+ printk(KERN_INFO "VFS: Can't find a valid"
+ " VFAT filesystem on dev %s.\n", sb->s_id);
+ return NULL;
+ }
if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
MSDOS_SB(sb)->options.dotsOK = 0;
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h
--- pre1/linux/include/asm-arm/arch-arc/system.h Sun Aug 12 11:14:00 2001
+++ linux/include/asm-arm/arch-arc/system.h Tue Jan 15 13:53:51 2002
@@ -10,7 +10,7 @@
static void arch_idle(void)
{
- while (!current->need_resched && !hlt_counter);
+ while (!need_resched() && !hlt_counter);
}
static inline void arch_reset(char mode)
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-cl7500/system.h linux/include/asm-arm/arch-cl7500/system.h
--- pre1/linux/include/asm-arm/arch-cl7500/system.h Thu Apr 12 12:20:31 2001
+++ linux/include/asm-arm/arch-cl7500/system.h Tue Jan 15 13:53:51 2002
@@ -10,7 +10,7 @@
static void arch_idle(void)
{
- while (!current->need_resched && !hlt_counter)
+ while (!need_resched() && !hlt_counter)
iomd_writeb(0, IOMD_SUSMODE);
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-ebsa110/system.h linux/include/asm-arm/arch-ebsa110/system.h
--- pre1/linux/include/asm-arm/arch-ebsa110/system.h Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa110/system.h Tue Jan 15 13:53:51 2002
@@ -17,7 +17,7 @@
* will stop our MCLK signal (which provides the clock for the glue
* logic, and therefore the timer interrupt).
*
- * Instead, we spin, waiting for either hlt_counter or need_resched
+ * Instead, we spin, waiting for either hlt_counter or need_resched()
* to be set. If we have been spinning for 2cs, then we drop the
* core clock down to the memory clock.
*/
@@ -28,13 +28,13 @@
start_idle = jiffies;
do {
- if (current->need_resched || hlt_counter)
+ if (need_resched() || hlt_counter)
goto slow_out;
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
- while (!current->need_resched && !hlt_counter) {
+ while (!need_resched() && !hlt_counter) {
/* do nothing slowly */
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-ebsa285/system.h linux/include/asm-arm/arch-ebsa285/system.h
--- pre1/linux/include/asm-arm/arch-ebsa285/system.h Sun Aug 12 11:14:00 2001
+++ linux/include/asm-arm/arch-ebsa285/system.h Tue Jan 15 13:53:51 2002
@@ -20,14 +20,14 @@
start_idle = jiffies;
do {
- if (current->need_resched || hlt_counter)
+ if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
- while (!current->need_resched && !hlt_counter) {
+ while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h
--- pre1/linux/include/asm-arm/arch-nexuspci/system.h Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-nexuspci/system.h Tue Jan 15 13:53:51 2002
@@ -16,7 +16,7 @@
static void arch_idle(void)
{
- while (!current->need_resched && !hlt_counter)
+ while (!need_resched() && !hlt_counter)
cpu_do_idle(IDLE_WAIT_SLOW);
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- pre1/linux/include/asm-arm/arch-rpc/system.h Sun Aug 12 11:14:00 2001
+++ linux/include/asm-arm/arch-rpc/system.h Tue Jan 15 13:53:51 2002
@@ -18,14 +18,14 @@
start_idle = jiffies;
do {
- if (current->need_resched || hlt_counter)
+ if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
- while (!current->need_resched && !hlt_counter) {
+ while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-sa1100/system.h linux/include/asm-arm/arch-sa1100/system.h
--- pre1/linux/include/asm-arm/arch-sa1100/system.h Thu Oct 25 13:53:54 2001
+++ linux/include/asm-arm/arch-sa1100/system.h Tue Jan 15 13:53:51 2002
@@ -10,7 +10,7 @@
if (!hlt_counter) {
int flags;
local_irq_save(flags);
- if (!current->need_resched)
+ if (!need_resched())
cpu_do_idle(0);
local_irq_restore(flags);
}
diff -u --recursive --new-file pre1/linux/include/asm-arm/arch-tbox/system.h linux/include/asm-arm/arch-tbox/system.h
--- pre1/linux/include/asm-arm/arch-tbox/system.h Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-tbox/system.h Tue Jan 15 13:53:51 2002
@@ -13,14 +13,14 @@
start_idle = jiffies;
do {
- if (current->need_resched || hlt_counter)
+ if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
- while (!current->need_resched && !hlt_counter) {
+ while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
diff -u --recursive --new-file pre1/linux/include/asm-i386/mmu_context.h linux/include/asm-i386/mmu_context.h
--- pre1/linux/include/asm-i386/mmu_context.h Mon Jan 14 13:27:07 2002
+++ linux/include/asm-i386/mmu_context.h Thu Jan 17 17:13:00 2002
@@ -1,5 +1,5 @@
-#ifndef __I386_MMU_CONTEXT_H
-#define __I386_MMU_CONTEXT_H
+#ifndef __I386_SCHED_H
+#define __I386_SCHED_H
#include
#include
@@ -16,14 +16,13 @@
# error update this function.
#endif
-static inline int sched_find_first_zero_bit(char *bitmap)
+static inline int sched_find_first_zero_bit(unsigned long *b)
{
- unsigned int *b = (unsigned int *)bitmap;
unsigned int rt;
rt = b[0] & b[1] & b[2] & b[3];
if (unlikely(rt != 0xffffffff))
- return find_first_zero_bit(bitmap, MAX_RT_PRIO);
+ return find_first_zero_bit(b, MAX_RT_PRIO);
if (b[4] != ~0)
return ffz(b[4]) + MAX_RT_PRIO;
diff -u --recursive --new-file pre1/linux/include/asm-i386/smplock.h linux/include/asm-i386/smplock.h
--- pre1/linux/include/asm-i386/smplock.h Mon Jan 14 13:27:16 2002
+++ linux/include/asm-i386/smplock.h Thu Jan 17 17:10:31 2002
@@ -19,8 +19,8 @@
do { \
if (unlikely(task->lock_depth >= 0)) { \
spin_unlock(&kernel_flag); \
- release_irqlock(cpu); \
- __sti(); \
+ if (global_irq_holder == (cpu)) \
+ BUG(); \
} \
} while (0)
diff -u --recursive --new-file pre1/linux/include/linux/blk.h linux/include/linux/blk.h
--- pre1/linux/include/linux/blk.h Mon Jan 14 13:28:11 2002
+++ linux/include/linux/blk.h Thu Jan 17 17:11:37 2002
@@ -90,9 +90,9 @@
#define _elv_add_request(q, rq, back, p) do { \
if ((back)) \
- _elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+ _elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
else \
- _elv_add_request_core((q), (rq), &(q)->queue_head, 0); \
+ _elv_add_request_core((q), (rq), &(q)->queue_head, (p)); \
} while (0)
#define elv_add_request(q, rq, back) _elv_add_request((q), (rq), (back), 1)
diff -u --recursive --new-file pre1/linux/include/linux/file.h linux/include/linux/file.h
--- pre1/linux/include/linux/file.h Wed Jan 16 11:16:28 2002
+++ linux/include/linux/file.h Thu Jan 17 17:10:22 2002
@@ -5,12 +5,9 @@
#ifndef __LINUX_FILE_H
#define __LINUX_FILE_H
-#ifndef _LINUX_POSIX_TYPES_H /* __FD_CLR */
+#include
#include
-#endif
-#ifndef __LINUX_COMPILER_H /* unlikely */
#include
-#endif
/*
* The default fd array needs to be at least BITS_PER_LONG,
diff -u --recursive --new-file pre1/linux/include/linux/fs.h linux/include/linux/fs.h
--- pre1/linux/include/linux/fs.h Mon Jan 14 13:27:08 2002
+++ linux/include/linux/fs.h Thu Jan 17 17:10:23 2002
@@ -262,7 +262,7 @@
wait_queue_head_t b_wait;
- struct inode * b_inode;
+ int b_inode; /* will go away */
struct list_head b_inode_buffers; /* doubly linked list of inode dirty buffers */
};
@@ -859,6 +859,9 @@
* without the big kernel lock held in all filesystems.
*/
struct super_operations {
+ struct inode *(*alloc_inode)(struct super_block *sb);
+ void (*destroy_inode)(struct inode *);
+
void (*read_inode) (struct inode *);
/* reiserfs kludge. reiserfs needs 64 bits of information to
@@ -1151,7 +1154,16 @@
extern void FASTCALL(__mark_dirty(struct buffer_head *bh));
extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh));
extern void FASTCALL(mark_buffer_dirty(struct buffer_head *bh));
-extern void FASTCALL(buffer_insert_inode_data_queue(struct buffer_head *, struct inode *));
+extern void FASTCALL(buffer_insert_list(struct buffer_head *, struct list_head *));
+
+static inline void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
+{
+ buffer_insert_list(bh, &inode->i_dirty_buffers);
+}
+static inline void buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode)
+{
+ buffer_insert_list(bh, &inode->i_dirty_data_buffers);
+}
#define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state)
@@ -1219,10 +1231,16 @@
extern int fsync_super(struct super_block *);
extern int fsync_no_super(struct block_device *);
extern void sync_inodes_sb(struct super_block *);
-extern int osync_inode_buffers(struct inode *);
-extern int osync_inode_data_buffers(struct inode *);
-extern int fsync_inode_buffers(struct inode *);
-extern int fsync_inode_data_buffers(struct inode *);
+extern int osync_buffers_list(struct list_head *);
+extern int fsync_buffers_list(struct list_head *);
+static inline int fsync_inode_buffers(struct inode *inode)
+{
+ return fsync_buffers_list(&inode->i_dirty_buffers);
+}
+static inline int fsync_inode_data_buffers(struct inode *inode)
+{
+ return fsync_buffers_list(&inode->i_dirty_data_buffers);
+}
extern int inode_has_buffers(struct inode *);
extern void filemap_fdatasync(struct address_space *);
extern void filemap_fdatawait(struct address_space *);
@@ -1327,6 +1345,7 @@
#define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
#define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
+extern void inode_init_once(struct inode *);
extern void iput(struct inode *);
extern void force_delete(struct inode *);
extern struct inode * igrab(struct inode *);
@@ -1340,20 +1359,8 @@
}
extern void clear_inode(struct inode *);
-extern struct inode * get_empty_inode(void);
-
-static inline struct inode * new_inode(struct super_block *sb)
-{
- struct inode *inode = get_empty_inode();
- if (inode) {
- inode->i_sb = sb;
- inode->i_dev = sb->s_dev;
- inode->i_blkbits = sb->s_blocksize_bits;
- }
- return inode;
-}
+extern struct inode *new_inode(struct super_block *);
extern void remove_suid(struct inode *inode);
-
extern void insert_inode_hash(struct inode *);
extern void remove_inode_hash(struct inode *);
extern struct file * get_empty_filp(void);
diff -u --recursive --new-file pre1/linux/include/linux/ide.h linux/include/linux/ide.h
--- pre1/linux/include/linux/ide.h Wed Jan 16 11:16:28 2002
+++ linux/include/linux/ide.h Thu Jan 17 17:11:37 2002
@@ -884,6 +884,9 @@
*/
#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
+#define task_rq_offset(rq) \
+ (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE)
+
extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags)
{
return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
@@ -892,6 +895,24 @@
extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags)
{
bio_kunmap_irq(buffer, flags);
+}
+
+/*
+ * for now, taskfile requests are special :/
+ */
+extern inline char *ide_map_rq(struct request *rq, unsigned long *flags)
+{
+ if (rq->bio)
+ return ide_map_buffer(rq, flags);
+ else
+ return rq->buffer + task_rq_offset(rq);
+}
+
+extern inline void ide_unmap_rq(struct request *rq, char *buf,
+ unsigned long *flags)
+{
+ if (rq->bio)
+ ide_unmap_buffer(buf, flags);
}
/*
diff -u --recursive --new-file pre1/linux/include/linux/init.h linux/include/linux/init.h
--- pre1/linux/include/linux/init.h Mon Jan 14 13:27:05 2002
+++ linux/include/linux/init.h Thu Jan 17 17:10:21 2002
@@ -50,8 +50,26 @@
extern initcall_t __initcall_start, __initcall_end;
-#define __initcall(fn) \
- static initcall_t __initcall_##fn __init_call = fn
+/* initcalls are now grouped by functionality into separate
+ * subsections. Ordering inside the subsections is determined
+ * by link order.
+ * For backwards compatability, initcall() puts the call in
+ * the device init subsection.
+ */
+
+#define __define_initcall(level,fn) \
+ static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".initcall" level ".init"))) = fn
+
+#define early_arch_initcall(fn) __define_initcall("1",fn)
+#define mem_initcall(fn) __define_initcall("2",fn)
+#define subsys_initcall(fn) __define_initcall("3",fn)
+#define arch_initcall(fn) __define_initcall("4",fn)
+#define fs_initcall(fn) __define_initcall("5",fn)
+#define device_initcall(fn) __define_initcall("6",fn)
+#define late_initcall(fn) __define_initcall("7",fn)
+
+#define __initcall(fn) device_initcall(fn)
+
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
@@ -80,7 +98,7 @@
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
#define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
-#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
+#define __init_call(level) __attribute__ ((unused,__section__ (".initcall" level ".init")))
#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
/* For assembly routines */
@@ -140,6 +158,14 @@
{ return x; }
#define __setup(str,func) /* nothing */
+
+#define early_arch_initcall(fn) module_init(fn)
+#define mem_initcall(fn) module_init(fn)
+#define subsys_initcall(fn) module_init(fn)
+#define arch_initcall(fn) module_init(fn)
+#define fs_initcall(fn) module_init(fn)
+#define device_initcall(fn) module_init(fn)
+#define late_initcall(fn) module_init(fn)
#endif
diff -u --recursive --new-file pre1/linux/include/linux/init_task.h linux/include/linux/init_task.h
--- pre1/linux/include/linux/init_task.h Wed Jan 16 11:16:28 2002
+++ linux/include/linux/init_task.h Thu Jan 17 17:14:50 2002
@@ -1,9 +1,7 @@
#ifndef _LINUX__INIT_TASK_H
#define _LINUX__INIT_TASK_H
-#ifndef __LINUX_FILE_H
#include
-#endif
#define INIT_FILES \
{ \
diff -u --recursive --new-file pre1/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- pre1/linux/include/linux/isdn.h Sun Dec 30 10:31:51 2001
+++ linux/include/linux/isdn.h Thu Jan 17 14:04:15 2002
@@ -178,8 +178,6 @@
* the correspondent code in isdn.c
*/
-#define ISDN_MINOR_B 0
-#define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1)
#define ISDN_MINOR_CTRL 64
#define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1))
#define ISDN_MINOR_PPP 128
diff -u --recursive --new-file pre1/linux/include/linux/mtd/cfi.h linux/include/linux/mtd/cfi.h
--- pre1/linux/include/linux/mtd/cfi.h Thu Oct 4 15:13:18 2001
+++ linux/include/linux/mtd/cfi.h Tue Jan 15 13:53:51 2002
@@ -368,7 +368,7 @@
static inline void cfi_udelay(int us)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if (current->need_resched) {
+ if (need_resched()) {
unsigned long t = us * HZ / 1000000;
if (t < 1)
t = 1;
diff -u --recursive --new-file pre1/linux/include/linux/pci.h linux/include/linux/pci.h
--- pre1/linux/include/linux/pci.h Mon Jan 14 13:28:08 2002
+++ linux/include/linux/pci.h Thu Jan 17 17:11:07 2002
@@ -525,7 +525,6 @@
/* Generic PCI functions used internally */
-void pci_init(void);
int pci_bus_exists(const struct list_head *list, int nr);
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_alloc_primary_bus(int bus);
diff -u --recursive --new-file pre1/linux/include/linux/reiserfs_fs_sb.h linux/include/linux/reiserfs_fs_sb.h
--- pre1/linux/include/linux/reiserfs_fs_sb.h Mon Jan 14 13:27:06 2002
+++ linux/include/linux/reiserfs_fs_sb.h Thu Jan 17 17:10:23 2002
@@ -300,7 +300,7 @@
int j_free_bitmap_nodes ;
int j_used_bitmap_nodes ;
struct list_head j_bitmap_nodes ;
- struct inode j_dummy_inode ;
+ struct list_head j_dirty_buffers ;
struct reiserfs_list_bitmap j_list_bitmap[JOURNAL_NUM_BITMAPS] ; /* array of bitmaps to record the deleted blocks */
struct reiserfs_journal_list j_journal_list[JOURNAL_LIST_COUNT] ; /* array of all the journal lists */
struct reiserfs_journal_cnode *j_hash_table[JOURNAL_HASH_SIZE] ; /* hash table for real buffer heads in current trans */
diff -u --recursive --new-file pre1/linux/include/linux/sched.h linux/include/linux/sched.h
--- pre1/linux/include/linux/sched.h Wed Jan 16 11:16:28 2002
+++ linux/include/linux/sched.h Thu Jan 17 17:10:23 2002
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
struct exec_domain;
@@ -136,6 +137,8 @@
extern rwlock_t tasklist_lock;
extern spinlock_t mmlist_lock;
+typedef struct task_struct task_t;
+
extern void sched_init(void);
extern void init_idle(void);
extern void show_state(void);
@@ -144,8 +147,7 @@
extern void update_process_times(int user);
extern void update_one_process(struct task_struct *p, unsigned long user,
unsigned long system, int cpu);
-extern void expire_task(struct task_struct *p);
-extern void idle_tick(void);
+extern void scheduler_tick(struct task_struct *p);
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
extern signed long FASTCALL(schedule_timeout(signed long timeout));
@@ -221,7 +223,6 @@
extern struct user_struct root_user;
#define INIT_USER (&root_user)
-typedef struct task_struct task_t;
typedef struct prio_array prio_array_t;
struct task_struct {
@@ -251,7 +252,10 @@
prio_array_t *array;
unsigned int time_slice;
- unsigned long sleep_jtime;
+
+ #define MAX_SLEEP_AVG (2*HZ)
+ unsigned long sleep_avg;
+ unsigned long sleep_timestamp;
unsigned long policy;
unsigned long cpus_allowed;
@@ -390,30 +394,47 @@
* them out at 128 to make it easier to search the
* scheduler bitmap.
*/
-#define MAX_RT_PRIO 128
+#define MAX_RT_PRIO 128
/*
* The lower the priority of a process, the more likely it is
* to run. Priority of a process goes from 0 to 167. The 0-99
* priority range is allocated to RT tasks, the 128-167 range
* is for SCHED_OTHER tasks.
*/
-#define MAX_PRIO (MAX_RT_PRIO+40)
-#define DEF_USER_NICE 0
+#define MAX_PRIO (MAX_RT_PRIO + 40)
/*
- * Default timeslice is 80 msecs, maximum is 160 msecs.
+ * Scales user-nice values [ -20 ... 0 ... 19 ]
+ * to static priority [ 128 ... 167 (MAX_PRIO-1) ]
+ *
+ * User-nice value of -20 == static priority 128, and
+ * user-nice value 19 == static priority 167. The lower
+ * the priority value, the higher the task's priority.
+ */
+#define NICE_TO_PRIO(n) (MAX_RT_PRIO + (n) + 20)
+#define DEF_USER_NICE 0
+
+/*
+ * Default timeslice is 90 msecs, maximum is 180 msecs.
* Minimum timeslice is 10 msecs.
*/
-#define MIN_TIMESLICE (10 * HZ / 1000)
-#define MAX_TIMESLICE (160 * HZ / 1000)
+#define MIN_TIMESLICE ( 10 * HZ / 1000)
+#define MAX_TIMESLICE (180 * HZ / 1000)
-#define USER_PRIO(p) ((p)-MAX_RT_PRIO)
-#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
-#define DEF_PRIO (MAX_RT_PRIO + MAX_USER_PRIO / 3)
-#define NICE_TO_PRIO(n) (MAX_PRIO-1 + (n) - 19)
+#define USER_PRIO(p) ((p)-MAX_RT_PRIO)
+#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
-#define NICE_TO_TIMESLICE(n) (MIN_TIMESLICE + \
- ((MAX_TIMESLICE - MIN_TIMESLICE) * (19 - (n))) / 39)
+/*
+ * NICE_TO_TIMESLICE scales nice values [ -20 ... 19 ]
+ * to time slice values.
+ *
+ * The higher a process's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority process gets MIN_TIMESLICE worth of execution time.
+ */
+
+#define NICE_TO_TIMESLICE(n) (MIN_TIMESLICE + \
+ ((MAX_TIMESLICE - MIN_TIMESLICE) * (19-(n))) / 39)
extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
extern void set_user_nice(task_t *p, long nice);
@@ -541,6 +562,17 @@
static inline int signal_pending(struct task_struct *p)
{
return (p->sigpending != 0);
+}
+
+static inline int need_resched(void)
+{
+ return unlikely(current->need_resched != 0);
+}
+
+static inline void cond_resched(void)
+{
+ if (need_resched())
+ schedule();
}
/*
diff -u --recursive --new-file pre1/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- pre1/linux/include/scsi/sg.h Fri Sep 7 09:28:37 2001
+++ linux/include/scsi/sg.h Thu Jan 17 13:59:33 2002
@@ -11,78 +11,71 @@
Version 2 and 3 extensions to driver:
* Copyright (C) 1998 - 2001 Douglas Gilbert
- Version: 3.1.20 (20010814)
- This version is for 2.4 series kernels.
+ Version: 3.5.23 (20011231)
+ This version is for 2.5 series kernels.
- Changes since 3.1.19 (20010623)
- - add SG_GET_ACCESS_COUNT ioctl
- - make open() increment and close() decrement access_count
- - only register first 256 devices, reject subsequent devices
- Changes since 3.1.18 (20010505)
- - fix bug that caused long wait when large buffer requested
- - fix leak in error case of sg_new_read() [report: Eric Barton]
- - add 'online' column to /proc/scsi/sg/devices
- Changes since 3.1.17 (20000921)
- - add CAP_SYS_RAWIO capability for sensitive stuff
- - compile in dio stuff, procfs 'allow_dio' defaulted off (0)
- - make premature close and detach more robust
- - lun masked into commands <= SCSI_2
- - poll() and async notification now yield POLL_HUP on detach
- - various 3rd party tweaks tracking lk 2.4 internal changes
+ Changes since 3.1.22 (20011208)
+ - branch sg driver for lk 2.5 series
+ - remove lock_kernel() from sg_close()
+ - remove code based on scsi mid level dma pool
+ - change scatterlist 'address' to use page + offset
+ - add SG_INTERFACE_ID_ORIG
Map of SG verions to the Linux kernels in which they appear:
---------- ----------------------------------
original all kernels < 2.2.6
- 2.1.38 2.2.16
- 2.1.39 2.2.17 - 2.2.19
+ 2.1.40 2.2.20
3.0.x optional version 3 sg driver for 2.2 series
- 3.1.17 2.4.0 ++
+ 3.1.17++ 2.4.0++
+ 3.5.23++ 2.5.0++
Major new features in SG 3.x driver (cf SG 2.x drivers)
- SG_IO ioctl() combines function if write() and read()
- new interface (sg_io_hdr_t) but still supports old interface
- - scatter/gather in user space and direct IO supported
+ - scatter/gather in user space, direct IO, and mmap supported
- The term "indirect IO" refers a method by which data is DMAed into kernel
- buffers from the hardware and afterwards is transferred into the user
- space (or vice versa if you are writing). Transfer speeds of up to 20 to
- 30MBytes/sec have been measured using indirect IO. For faster throughputs
- "direct IO" which cuts out the double handling of data is required.
- Direct IO is supported by the SG 3.x drivers on 2.4 series Linux kernels
- and requires the use of the new interface.
-
- Requests for direct IO with the new interface will automatically fall back
- to indirect IO mode if they cannot be fulfilled. An example of such a case
- is an ISA SCSI adapter which is only capable of DMAing to the lower 16MB of
- memory due to the architecture of ISA. The 'info' field in the new
- interface indicates whether a direct or indirect data transfer took place.
-
- Obtaining memory for the kernel buffers used in indirect IO is done by
- first checking if the "reserved buffer" for the current file descriptor
- is available and large enough. If these conditions are _not_ met then
- kernel memory is obtained on a per SCSI command basis. This corresponds
- to a write(), read() sequence or a SG_IO ioctl() call. Further, the
- kernel memory that is suitable for DMA may be constrained by the
- architecture of the SCSI adapter (e.g. ISA adapters).
+ The normal action of this driver is to use the adapter (HBA) driver to DMA
+ data into kernel buffers and then use the CPU to copy the data into the
+ user space (vice versa for writes). That is called "indirect" IO due to
+ the double handling of data. There are two methods offered to remove the
+ redundant copy: 1) direct IO which uses the kernel kiobuf mechanism and
+ 2) using the mmap() system call to map the reserve buffer (this driver has
+ one reserve buffer per fd) into the user space. Both have their advantages.
+ In terms of absolute speed mmap() is faster. If speed is not a concern,
+ indirect IO should be fine. Read the documentation for more information.
** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' may be
needed. That pseudo file's content is defaulted to 0. **
+
+ Historical note: this SCSI pass-through driver has been known as "sg" for
+ a decade. In broader kernel discussions "sg" is used to refer to scatter
+ gather techniques. The context should clarify which "sg" is referred to.
Documentation
=============
- A web site for SG device drivers can be found at:
+ A web site for the SG device driver can be found at:
http://www.torque.net/sg [alternatively check the MAINTAINERS file]
- The main documents are still based on 2.x versions:
+ The documentation for the sg version 3 driver can be found at:
+ http://www.torque.net/sg/p/sg_v3_ho.html
+ This is a rendering from DocBook source [change the extension to "sgml"
+ or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon).
+
+ The older, version 2 documents discuss the original sg interface in detail:
http://www.torque.net/sg/p/scsi-generic.txt
http://www.torque.net/sg/p/scsi-generic_long.txt
- Documentation on the changes and additions in 3.x version of the sg driver
- can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt
A version of this document (potentially out of date) may also be found in
the kernel source tree, probably at:
/usr/src/linux/Documentation/scsi-generic.txt .
- Utility and test programs are available at the sg web site.
+
+ Utility and test programs are available at the sg web site. They are
+ bundled as sg_utils (for the lk 2.2 series) and sg3_utils (for the
+ lk 2.4 series).
+
+ There is a HOWTO on the Linux SCSI subsystem in the lk 2.4 series at:
+ http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO
*/
+
/* New interface introduced in the 3.x SG drivers follows */
typedef struct sg_iovec /* same structure as used by readv() Linux system */
@@ -119,20 +112,23 @@
unsigned int info; /* [o] auxiliary information */
} sg_io_hdr_t; /* 64 bytes long (on i386) */
+#define SG_INTERFACE_ID_ORIG 'S'
+
/* Use negative values to flag difference from original sg_header structure */
-#define SG_DXFER_NONE -1 /* e.g. a SCSI Test Unit Ready command */
-#define SG_DXFER_TO_DEV -2 /* e.g. a SCSI WRITE command */
-#define SG_DXFER_FROM_DEV -3 /* e.g. a SCSI READ command */
-#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the
+#define SG_DXFER_NONE (-1) /* e.g. a SCSI Test Unit Ready command */
+#define SG_DXFER_TO_DEV (-2) /* e.g. a SCSI WRITE command */
+#define SG_DXFER_FROM_DEV (-3) /* e.g. a SCSI READ command */
+#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
additional property than during indirect
IO the user buffer is copied into the
kernel buffers before the transfer */
-#define SG_DXFER_UNKNOWN -5 /* Unknown data direction */
+#define SG_DXFER_UNKNOWN (-5) /* Unknown data direction */
/* following flag values can be "or"-ed together */
#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */
-#define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */
- /* the 2nd byte of SCSI command */
+#define SG_FLAG_LUN_INHIBIT 2 /* default is overwrite lun in SCSI */
+ /* command block (when <= SCSI_2) */
+#define SG_FLAG_MMAP_IO 4 /* request memory mapped IO */
#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
/* user space (debug indirect IO) */
diff -u --recursive --new-file pre1/linux/init/main.c linux/init/main.c
--- pre1/linux/init/main.c Wed Jan 9 09:45:17 2002
+++ linux/init/main.c Thu Jan 17 14:21:16 2002
@@ -38,35 +38,10 @@
#include
#endif
-#ifdef CONFIG_PCI
-#include
-#endif
-
-#ifdef CONFIG_DIO
-#include
-#endif
-
-#ifdef CONFIG_ZORRO
-#include
-#endif
-
#ifdef CONFIG_MTRR
# include
#endif
-#ifdef CONFIG_NUBUS
-#include
-#endif
-
-#ifdef CONFIG_ISAPNP
-#include
-#endif
-
-#ifdef CONFIG_IRDA
-extern int irda_proto_init(void);
-extern int irda_device_init(void);
-#endif
-
#ifdef CONFIG_X86_LOCAL_APIC
#include
#endif
@@ -92,10 +67,8 @@
extern void fork_init(unsigned long);
extern void mca_init(void);
extern void sbus_init(void);
-extern void ppc_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
-extern int init_pcmcia_ds(void);
extern void free_initmem(void);
@@ -103,8 +76,6 @@
extern void tc_init(void);
#endif
-extern void ecard_init(void);
-
#if defined(CONFIG_SYSVIPC)
extern void ipc_init(void);
#endif
@@ -490,50 +461,11 @@
/* bring up the device tree */
device_driver_init();
-#ifdef CONFIG_PCI
- pci_init();
-#endif
-#ifdef CONFIG_SBUS
- sbus_init();
-#endif
-#if defined(CONFIG_PPC)
- ppc_init();
-#endif
-#ifdef CONFIG_MCA
- mca_init();
-#endif
-#ifdef CONFIG_ARCH_ACORN
- ecard_init();
-#endif
-#ifdef CONFIG_ZORRO
- zorro_init();
-#endif
-#ifdef CONFIG_DIO
- dio_init();
-#endif
-#ifdef CONFIG_NUBUS
- nubus_init();
-#endif
-#ifdef CONFIG_ISAPNP
- isapnp_init();
-#endif
-#ifdef CONFIG_TC
- tc_init();
-#endif
-
/* Networking initialization needs a process context */
sock_init();
start_context_thread();
do_initcalls();
-
-#ifdef CONFIG_IRDA
- irda_proto_init();
- irda_device_init(); /* Must be done after protocol initialization */
-#endif
-#ifdef CONFIG_PCMCIA
- init_pcmcia_ds(); /* Do this last */
-#endif
}
extern void prepare_namespace(void);
diff -u --recursive --new-file pre1/linux/kernel/fork.c linux/kernel/fork.c
--- pre1/linux/kernel/fork.c Wed Jan 16 11:16:28 2002
+++ linux/kernel/fork.c Tue Jan 15 14:33:55 2002
@@ -704,8 +704,9 @@
* runqueue lock is not a problem.
*/
current->time_slice = 1;
- expire_task(current);
+ scheduler_tick(current);
}
+ p->sleep_timestamp = jiffies;
__restore_flags(flags);
if (p->policy == SCHED_OTHER)
diff -u --recursive --new-file pre1/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- pre1/linux/kernel/ksyms.c Wed Jan 16 11:16:28 2002
+++ linux/kernel/ksyms.c Thu Jan 17 14:30:00 2002
@@ -137,6 +137,7 @@
EXPORT_SYMBOL(iunique);
EXPORT_SYMBOL(iget4);
EXPORT_SYMBOL(iput);
+EXPORT_SYMBOL(inode_init_once);
EXPORT_SYMBOL(force_delete);
EXPORT_SYMBOL(follow_up);
EXPORT_SYMBOL(follow_down);
@@ -502,17 +503,16 @@
/* Added to make file system as module */
EXPORT_SYMBOL(sys_tz);
EXPORT_SYMBOL(file_fsync);
-EXPORT_SYMBOL(fsync_inode_buffers);
-EXPORT_SYMBOL(fsync_inode_data_buffers);
+EXPORT_SYMBOL(fsync_buffers_list);
EXPORT_SYMBOL(clear_inode);
EXPORT_SYMBOL(___strtok);
EXPORT_SYMBOL(init_special_inode);
EXPORT_SYMBOL(read_ahead);
EXPORT_SYMBOL(__get_hash_table);
-EXPORT_SYMBOL(get_empty_inode);
+EXPORT_SYMBOL(new_inode);
EXPORT_SYMBOL(insert_inode_hash);
EXPORT_SYMBOL(remove_inode_hash);
-EXPORT_SYMBOL(buffer_insert_inode_queue);
+EXPORT_SYMBOL(buffer_insert_list);
EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event);
diff -u --recursive --new-file pre1/linux/kernel/printk.c linux/kernel/printk.c
--- pre1/linux/kernel/printk.c Mon Jan 7 12:55:16 2002
+++ linux/kernel/printk.c Tue Jan 15 13:53:51 2002
@@ -524,7 +524,7 @@
*/
void console_conditional_schedule(void)
{
- if (console_may_schedule && current->need_resched) {
+ if (console_may_schedule && need_resched()) {
set_current_state(TASK_RUNNING);
schedule();
}
diff -u --recursive --new-file pre1/linux/kernel/sched.c linux/kernel/sched.c
--- pre1/linux/kernel/sched.c Wed Jan 16 11:16:28 2002
+++ linux/kernel/sched.c Tue Jan 15 14:33:55 2002
@@ -20,10 +20,7 @@
#include
#include
-#define BITMAP_SIZE ((MAX_PRIO+7)/8)
-#define PRIO_INTERACTIVE (MAX_RT_PRIO + (MAX_PRIO - MAX_RT_PRIO) / 3)
-#define TASK_INTERACTIVE(p) ((p)->prio >= MAX_RT_PRIO && (p)->prio <= PRIO_INTERACTIVE)
-#define JSLEEP_TO_PRIO(t) (((t) * 20) / HZ)
+#define BITMAP_SIZE ((((MAX_PRIO+7)/8)+sizeof(long)-1)/sizeof(long))
typedef struct runqueue runqueue_t;
@@ -31,7 +28,7 @@
int nr_active;
spinlock_t *lock;
runqueue_t *rq;
- char bitmap[BITMAP_SIZE];
+ unsigned long bitmap[BITMAP_SIZE];
list_t queue[MAX_PRIO];
};
@@ -40,33 +37,36 @@
*
* Locking rule: those places that want to lock multiple runqueues
* (such as the load balancing or the process migration code), lock
- * acquire operations must be ordered by rq->cpu.
+ * acquire operations must be ordered by the runqueue's cpu id.
*
* The RT event id is used to avoid calling into the the RT scheduler
* if there is a RT task active in an SMP system but there is no
* RT scheduling activity otherwise.
*/
-static struct runqueue {
- int cpu;
+struct runqueue {
spinlock_t lock;
unsigned long nr_running, nr_switches;
task_t *curr, *idle;
prio_array_t *active, *expired, arrays[2];
- char __pad [SMP_CACHE_BYTES];
-} runqueues [NR_CPUS] __cacheline_aligned;
+ int prev_nr_running[NR_CPUS];
+} ____cacheline_aligned;
+
+static struct runqueue runqueues[NR_CPUS] __cacheline_aligned;
-#define this_rq() (runqueues + smp_processor_id())
-#define task_rq(p) (runqueues + (p)->cpu)
#define cpu_rq(cpu) (runqueues + (cpu))
-#define cpu_curr(cpu) (runqueues[(cpu)].curr)
+#define this_rq() cpu_rq(smp_processor_id())
+#define task_rq(p) cpu_rq((p)->cpu)
+#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
+#define rq_cpu(rq) ((rq) - runqueues)
#define rt_task(p) ((p)->policy != SCHED_OTHER)
+
#define lock_task_rq(rq,p,flags) \
do { \
repeat_lock_task: \
rq = task_rq(p); \
spin_lock_irqsave(&rq->lock, flags); \
- if (unlikely((rq)->cpu != (p)->cpu)) { \
+ if (unlikely(rq_cpu(rq) != (p)->cpu)) { \
spin_unlock_irqrestore(&rq->lock, flags); \
goto repeat_lock_task; \
} \
@@ -94,18 +94,56 @@
p->array = array;
}
+/*
+ * A task is 'heavily interactive' if it has reached the
+ * bottom 25% of the SCHED_OTHER priority range - in this
+ * case we favor it by reinserting it on the active array,
+ * even after it expired its current timeslice.
+ *
+ * A task can get a priority bonus by being 'somewhat
+ * interactive' - and it will get a priority penalty for
+ * being a CPU hog.
+ *
+ * CPU-hog penalties cannot go more than 5 above the default
+ * priority level. Priority bonus cannot go below the minimum
+ * priority level.
+ */
+#define PRIO_INTERACTIVE (MAX_RT_PRIO + MAX_USER_PRIO/3)
+#define TASK_INTERACTIVE(p) ((p)->prio <= PRIO_INTERACTIVE)
+
+static inline int effective_prio(task_t *p)
+{
+ int bonus, prio;
+
+ /*
+ * Here we scale the actual sleep average [0 .... MAX_SLEEP_AVG]
+ * into the 20 ... -20 bonus/penalty range.
+ */
+ bonus = MAX_USER_PRIO * p->sleep_avg / MAX_SLEEP_AVG - MAX_USER_PRIO/2;
+ prio = NICE_TO_PRIO(p->__nice) - bonus;
+ if (prio < MAX_RT_PRIO)
+ prio = MAX_RT_PRIO;
+ if (prio > MAX_PRIO-1)
+ prio = MAX_PRIO-1;
+ return prio;
+}
+
static inline void activate_task(task_t *p, runqueue_t *rq)
{
prio_array_t *array = rq->active;
if (!rt_task(p)) {
- unsigned long prio_bonus = JSLEEP_TO_PRIO(jiffies - p->sleep_jtime);
-
- if (prio_bonus > MAX_PRIO)
- prio_bonus = MAX_PRIO;
- p->prio -= prio_bonus;
- if (p->prio < MAX_RT_PRIO)
- p->prio = MAX_RT_PRIO;
+ /*
+ * This code gives a bonus to interactive tasks. We update
+ * an 'average sleep time' value here, based on
+ * sleep_timestamp. The more time a task spends sleeping,
+ * the higher the average gets - and the higher the priority
+ * boost gets as well.
+ */
+ p->sleep_avg += jiffies - p->sleep_timestamp;
+ if (p->sleep_avg > MAX_SLEEP_AVG)
+ p->sleep_avg = MAX_SLEEP_AVG;
+ p->prio = effective_prio(p);
}
enqueue_task(p, array);
rq->nr_running++;
@@ -116,7 +154,7 @@
rq->nr_running--;
dequeue_task(p, p->array);
p->array = NULL;
- p->sleep_jtime = jiffies;
+ p->sleep_timestamp = jiffies;
}
static inline void resched_task(task_t *p)
@@ -206,13 +244,13 @@
{
runqueue_t *rq = this_rq();
- spin_lock_irq(&rq->lock);
p->state = TASK_RUNNING;
if (!rt_task(p)) {
p->prio += MAX_USER_PRIO/10;
if (p->prio > MAX_PRIO-1)
p->prio = MAX_PRIO-1;
}
+ spin_lock_irq(&rq->lock);
activate_task(p, rq);
spin_unlock_irq(&rq->lock);
}
@@ -287,59 +325,98 @@
}
/*
- * Current runqueue is empty, try to find work on
- * other runqueues.
+ * Current runqueue is empty, or rebalance tick: if there is an
+ * inbalance (current runqueue is too short) then pull from
+ * busiest runqueue(s).
*
* We call this with the current runqueue locked,
* irqs disabled.
*/
-static void load_balance(runqueue_t *this_rq)
+static void load_balance(runqueue_t *this_rq, int idle)
{
- int nr_tasks, load, prev_max_load, max_load, idx, i;
+ int imbalance, nr_running, load, prev_max_load,
+ max_load, idx, i, this_cpu = smp_processor_id();
task_t *next = this_rq->idle, *tmp;
- runqueue_t *busiest, *rq_tmp;
+ runqueue_t *busiest, *rq_src;
prio_array_t *array;
list_t *head, *curr;
- prev_max_load = max_rq_len();
- nr_tasks = prev_max_load - this_rq->nr_running;
- /*
- * It needs an at least ~10% imbalance to trigger balancing:
- */
- if (nr_tasks <= 1 + prev_max_load/8)
- return;
- prev_max_load++;
-
-repeat_search:
/*
* We search all runqueues to find the most busy one.
* We do this lockless to reduce cache-bouncing overhead,
- * we re-check the source CPU with the lock held.
+ * we re-check the 'best' source CPU later on again, with
+ * the lock held.
+ *
+ * We fend off statistical fluctuations in runqueue lengths by
+ * saving the runqueue length during the previous load-balancing
+ * operation and using the smaller one the current and saved lengths.
+ * If a runqueue is long enough for a longer amount of time then
+ * we recognize it and pull tasks from it.
+ *
+ * The 'current runqueue length' is a statistical maximum variable,
+ * for that one we take the longer one - to avoid fluctuations in
+ * the other direction. So for a load-balance to happen it needs
+ * stable long runqueue on the target CPU and stable short runqueue
+ * on the local runqueue.
+ *
+ * We make an exception if this CPU is about to become idle - in
+ * that case we are less picky about moving a task across CPUs and
+ * take what can be taken.
*/
+ if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+ nr_running = this_rq->nr_running;
+ else
+ nr_running = this_rq->prev_nr_running[this_cpu];
+ prev_max_load = 1000000000;
+
busiest = NULL;
max_load = 0;
for (i = 0; i < smp_num_cpus; i++) {
- rq_tmp = cpu_rq(i);
- load = rq_tmp->nr_running;
+ rq_src = cpu_rq(i);
+ if (idle || (rq_src->nr_running < this_rq->prev_nr_running[i]))
+ load = rq_src->nr_running;
+ else
+ load = this_rq->prev_nr_running[i];
+ this_rq->prev_nr_running[i] = rq_src->nr_running;
+
if ((load > max_load) && (load < prev_max_load) &&
- (rq_tmp != this_rq)) {
- busiest = rq_tmp;
+ (rq_src != this_rq)) {
+ busiest = rq_src;
max_load = load;
}
}
if (likely(!busiest))
return;
- if (max_load <= this_rq->nr_running)
+
+ imbalance = (max_load - nr_running) / 2;
+
+ /*
+ * It needs an at least ~25% imbalance to trigger balancing.
+ *
+ * prev_max_load makes sure that we do not try to balance
+ * ad infinitum - certain tasks might be impossible to be
+ * pulled into this runqueue.
+ */
+ if (!idle && (imbalance < (max_load + 3)/4))
return;
prev_max_load = max_load;
- if (busiest->cpu < this_rq->cpu) {
+
+ /*
+ * Ok, lets do some actual balancing:
+ */
+
+ if (rq_cpu(busiest) < this_cpu) {
spin_unlock(&this_rq->lock);
spin_lock(&busiest->lock);
spin_lock(&this_rq->lock);
} else
spin_lock(&busiest->lock);
- if (busiest->nr_running <= this_rq->nr_running + 1)
+ /*
+ * Make sure nothing changed since we checked the
+ * runqueue length.
+ */
+ if (busiest->nr_running <= nr_running + 1)
goto out_unlock;
/*
@@ -365,15 +442,14 @@
array = busiest->active;
goto new_array;
}
- spin_unlock(&busiest->lock);
- goto repeat_search;
+ goto out_unlock;
}
head = array->queue + idx;
curr = head->next;
skip_queue:
tmp = list_entry(curr, task_t, run_list);
- if ((tmp == busiest->curr) || !(tmp->cpus_allowed & (1 << smp_processor_id()))) {
+ if ((tmp == busiest->curr) || !(tmp->cpus_allowed & (1 << this_cpu))) {
curr = curr->next;
if (curr != head)
goto skip_queue;
@@ -387,64 +463,96 @@
*/
dequeue_task(next, array);
busiest->nr_running--;
- next->cpu = smp_processor_id();
+ next->cpu = this_cpu;
this_rq->nr_running++;
enqueue_task(next, this_rq->active);
if (next->prio < current->prio)
current->need_resched = 1;
- if (--nr_tasks) {
+ if (!idle && --imbalance) {
if (array == busiest->expired) {
array = busiest->active;
goto new_array;
}
- spin_unlock(&busiest->lock);
- goto repeat_search;
}
out_unlock:
spin_unlock(&busiest->lock);
}
-/* Rebalance every 250 msecs */
-#define REBALANCE_TICK (HZ/4)
+/*
+ * One of the idle_cpu_tick() or the busy_cpu_tick() function will
+ * gets called every timer tick, on every CPU. Our balancing action
+ * frequency and balancing agressivity depends on whether the CPU is
+ * idle or not.
+ *
+ * busy-rebalance every 250 msecs. idle-rebalance every 1 msec. (or on
+ * systems with HZ=100, every 10 msecs.)
+ */
+#define BUSY_REBALANCE_TICK (HZ/4 ?: 1)
+#define IDLE_REBALANCE_TICK (HZ/1000 ?: 1)
-void idle_tick(void)
+static inline void idle_tick(void)
{
- unsigned long flags;
-
- if (!(jiffies % REBALANCE_TICK) && likely(this_rq()->curr != NULL)) {
- spin_lock_irqsave(&this_rq()->lock, flags);
- load_balance(this_rq());
- spin_unlock_irqrestore(&this_rq()->lock, flags);
- }
+ if ((jiffies % IDLE_REBALANCE_TICK) ||
+ likely(this_rq()->curr == NULL))
+ return;
+ spin_lock(&this_rq()->lock);
+ load_balance(this_rq(), 1);
+ spin_unlock(&this_rq()->lock);
}
-void expire_task(task_t *p)
+/*
+ * This function gets called by the timer code, with HZ frequency.
+ * We call it with interrupts disabled.
+ */
+void scheduler_tick(task_t *p)
{
+ unsigned long now = jiffies;
runqueue_t *rq = this_rq();
- unsigned long flags;
+ if (p == rq->idle || !rq->idle)
+ return idle_tick();
+ /* Task might have expired already, but not scheduled off yet */
if (p->array != rq->active) {
p->need_resched = 1;
return;
}
+ spin_lock(&rq->lock);
+ if (unlikely(rt_task(p))) {
+ /*
+ * RR tasks need a special form of timeslice management.
+ * FIFO tasks have no timeslices.
+ */
+ if ((p->policy == SCHED_RR) && !--p->time_slice) {
+ p->time_slice = NICE_TO_TIMESLICE(p->__nice);
+ p->need_resched = 1;
+
+ /* put it at the end of the queue: */
+ dequeue_task(p, rq->active);
+ enqueue_task(p, rq->active);
+ }
+ goto out;
+ }
/*
- * The task cannot change CPUs because it's the current task.
+ * The task was running during this tick - update the
+ * time slice counter and the sleep average. Note: we
+ * do not update a process's priority until it either
+ * goes to sleep or uses up its timeslice. This makes
+ * it possible for interactive tasks to use up their
+ * timeslices at their high priority levels.
*/
- spin_lock_irqsave(&rq->lock, flags);
- if ((p->policy != SCHED_FIFO) && !--p->time_slice) {
- prio_array_t *array = rq->active;
- p->need_resched = 1;
+ if (p->sleep_avg)
+ p->sleep_avg--;
+ if (!--p->time_slice) {
dequeue_task(p, rq->active);
- if (!rt_task(p)) {
- if (++p->prio >= MAX_PRIO)
- p->prio = MAX_PRIO - 1;
- if (!TASK_INTERACTIVE(p))
- array = rq->expired;
- }
- enqueue_task(p, array);
+ p->need_resched = 1;
+ p->prio = effective_prio(p);
p->time_slice = NICE_TO_TIMESLICE(p->__nice);
+ enqueue_task(p, TASK_INTERACTIVE(p) ? rq->active : rq->expired);
}
- spin_unlock_irqrestore(&rq->lock, flags);
+out:
+ if (!(now % BUSY_REBALANCE_TICK))
+ load_balance(rq, 0);
+ spin_unlock(&rq->lock);
}
void scheduling_functions_start_here(void) { }
@@ -469,18 +577,18 @@
spin_lock_irq(&rq->lock);
switch (prev->state) {
- case TASK_INTERRUPTIBLE:
- if (unlikely(signal_pending(prev))) {
- prev->state = TASK_RUNNING;
- break;
- }
- default:
- deactivate_task(prev, rq);
- case TASK_RUNNING:
+ case TASK_INTERRUPTIBLE:
+ if (unlikely(signal_pending(prev))) {
+ prev->state = TASK_RUNNING;
+ break;
+ }
+ default:
+ deactivate_task(prev, rq);
+ case TASK_RUNNING:
}
pick_next_task:
if (unlikely(!rq->nr_running)) {
- load_balance(rq);
+ load_balance(rq, 1);
if (rq->nr_running)
goto pick_next_task;
next = rq->idle;
@@ -520,7 +628,7 @@
spin_unlock_irq(&rq->lock);
reacquire_kernel_lock(current);
- if (unlikely(current->need_resched))
+ if (need_resched())
goto need_resched_back;
return;
}
@@ -1015,7 +1123,7 @@
p = find_process_by_pid(pid);
if (p)
jiffies_to_timespec(p->policy & SCHED_FIFO ?
- 0 : NICE_TO_TIMESLICE(p->__nice), &t);
+ 0 : NICE_TO_TIMESLICE(p->prio), &t);
read_unlock(&tasklist_lock);
if (p)
retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
@@ -1123,7 +1231,7 @@
if (rq1 == rq2)
spin_lock(&rq1->lock);
else {
- if (rq1->cpu < rq2->cpu) {
+ if (rq_cpu(rq1) < rq_cpu(rq2)) {
spin_lock(&rq1->lock);
spin_lock(&rq2->lock);
} else {
@@ -1152,7 +1260,7 @@
this_rq->curr = this_rq->idle = current;
deactivate_task(current, rq);
current->array = NULL;
- current->prio = MAX_PRIO;
+ current->prio = MAX_PRIO-1;
current->state = TASK_RUNNING;
clear_bit(smp_processor_id(), &wait_init_idle);
double_rq_unlock(this_rq, rq);
@@ -1181,17 +1289,17 @@
rq->active = rq->arrays + 0;
rq->expired = rq->arrays + 1;
spin_lock_init(&rq->lock);
- rq->cpu = i;
for (j = 0; j < 2; j++) {
array = rq->arrays + j;
array->rq = rq;
array->lock = &rq->lock;
- for (k = 0; k < MAX_PRIO; k++)
+ for (k = 0; k < MAX_PRIO; k++) {
INIT_LIST_HEAD(array->queue + k);
- memset(array->bitmap, 0xff, BITMAP_SIZE);
+ __set_bit(k, array->bitmap);
+ }
// zero delimiter for bitsearch
- clear_bit(MAX_PRIO, array->bitmap);
+ __clear_bit(MAX_PRIO, array->bitmap);
}
}
/*
@@ -1202,9 +1310,6 @@
rq->curr = current;
rq->idle = NULL;
wake_up_process(current);
-
- for (i = 0; i < PIDHASH_SZ; i++)
- pidhash[i] = NULL;
init_timervecs();
init_bh(TIMER_BH, timer_bh);
diff -u --recursive --new-file pre1/linux/kernel/softirq.c linux/kernel/softirq.c
--- pre1/linux/kernel/softirq.c Mon Jan 7 12:55:16 2002
+++ linux/kernel/softirq.c Tue Jan 15 13:53:51 2002
@@ -387,8 +387,7 @@
while (softirq_pending(cpu)) {
do_softirq();
- if (current->need_resched)
- schedule();
+ cond_resched();
}
__set_current_state(TASK_INTERRUPTIBLE);
diff -u --recursive --new-file pre1/linux/kernel/timer.c linux/kernel/timer.c
--- pre1/linux/kernel/timer.c Mon Jan 7 12:55:16 2002
+++ linux/kernel/timer.c Tue Jan 15 14:33:55 2002
@@ -585,17 +585,16 @@
update_one_process(p, user_tick, system, cpu);
if (p->pid) {
- expire_task(p);
if (p->__nice > 0)
kstat.per_cpu_nice[cpu] += user_tick;
else
kstat.per_cpu_user[cpu] += user_tick;
kstat.per_cpu_system[cpu] += system;
} else {
- idle_tick();
if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
kstat.per_cpu_system[cpu] += system;
}
+ scheduler_tick(p);
}
/*
diff -u --recursive --new-file pre1/linux/mm/filemap.c linux/mm/filemap.c
--- pre1/linux/mm/filemap.c Wed Jan 16 11:16:28 2002
+++ linux/mm/filemap.c Tue Jan 15 13:53:51 2002
@@ -290,7 +290,7 @@
page_cache_release(page);
- if (current->need_resched) {
+ if (need_resched()) {
__set_current_state(TASK_RUNNING);
schedule();
}
@@ -400,7 +400,7 @@
}
page_cache_release(page);
- if (current->need_resched) {
+ if (need_resched()) {
__set_current_state(TASK_RUNNING);
schedule();
}
diff -u --recursive --new-file pre1/linux/mm/highmem.c linux/mm/highmem.c
--- pre1/linux/mm/highmem.c Mon Jan 14 10:10:43 2002
+++ linux/mm/highmem.c Thu Jan 17 13:59:33 2002
@@ -367,12 +367,6 @@
if (pfn >= blk_max_pfn)
return;
-#ifndef CONFIG_HIGHMEM
- /*
- * should not hit for non-highmem case
- */
- BUG();
-#endif
bio_gfp = GFP_NOHIGHIO;
pool = page_pool;
} else {
diff -u --recursive --new-file pre1/linux/mm/swapfile.c linux/mm/swapfile.c
--- pre1/linux/mm/swapfile.c Wed Jan 16 11:16:28 2002
+++ linux/mm/swapfile.c Tue Jan 15 13:53:51 2002
@@ -696,7 +696,7 @@
* interactive performance. Interruptible check on
* signal_pending() would be nice, but changes the spec?
*/
- if (current->need_resched)
+ if (need_resched())
schedule();
}
diff -u --recursive --new-file pre1/linux/mm/vmscan.c linux/mm/vmscan.c
--- pre1/linux/mm/vmscan.c Sat Dec 29 17:30:07 2001
+++ linux/mm/vmscan.c Tue Jan 15 13:53:51 2002
@@ -300,7 +300,7 @@
counter = mmlist_nr;
do {
- if (unlikely(current->need_resched)) {
+ if (need_resched()) {
__set_current_state(TASK_RUNNING);
schedule();
}
@@ -345,7 +345,7 @@
while (--max_scan >= 0 && (entry = inactive_list.prev) != &inactive_list) {
struct page * page;
- if (unlikely(current->need_resched)) {
+ if (need_resched()) {
spin_unlock(&pagemap_lru_lock);
__set_current_state(TASK_RUNNING);
schedule();
@@ -625,8 +625,7 @@
for (i = pgdat->nr_zones-1; i >= 0; i--) {
zone = pgdat->node_zones + i;
- if (unlikely(current->need_resched))
- schedule();
+ cond_resched();
if (!zone->need_balance)
continue;
if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) {
diff -u --recursive --new-file pre1/linux/net/ipv4/netfilter/ip_fw_compat_redir.c linux/net/ipv4/netfilter/ip_fw_compat_redir.c
--- pre1/linux/net/ipv4/netfilter/ip_fw_compat_redir.c Wed Jan 16 11:16:28 2002
+++ linux/net/ipv4/netfilter/ip_fw_compat_redir.c Wed Jan 16 10:29:38 2002
@@ -270,8 +270,10 @@
if (redir) {
DEBUGP("Doing tcp redirect again.\n");
do_tcp_redir(skb, redir);
- if (del_timer(&redir->destroyme))
- add_timer(&redir->destroyme, jiffies + REDIR_TIMEOUT);
+ if (del_timer(&redir->destroyme)) {
+ redir->destroyme.expires = jiffies + REDIR_TIMEOUT;
+ add_timer(&redir->destroyme);
+ }
}
UNLOCK_BH(&redir_lock);
}
@@ -296,8 +298,10 @@
if (redir) {
DEBUGP("Doing tcp unredirect.\n");
do_tcp_unredir(skb, redir);
- if (del_timer(&redir->destroyme))
- add_timer(&redir->destroyme, jiffies + REDIR_TIMEOUT);
+ if (del_timer(&redir->destroyme)) {
+ redir->destroyme.expires = jiffies + REDIR_TIMEOUT;
+ add_timer(&redir->destroyme);
+ }
}
UNLOCK_BH(&redir_lock);
}
diff -u --recursive --new-file pre1/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- pre1/linux/net/irda/af_irda.c Fri Nov 30 13:25:10 2001
+++ linux/net/irda/af_irda.c Thu Jan 17 14:21:16 2002
@@ -2590,14 +2590,11 @@
register_netdevice_notifier(&irda_dev_notifier);
irda_init();
-#ifdef MODULE
- irda_device_init(); /* Called by init/main.c when non-modular */
-#endif
+ irda_device_init();
return 0;
}
-#ifdef MODULE
-module_init(irda_proto_init); /* If non-module, called from init/main.c */
-#endif
+
+late_initcall(irda_proto_init);
/*
* Function irda_proto_cleanup (void)
diff -u --recursive --new-file pre1/linux/net/socket.c linux/net/socket.c
--- pre1/linux/net/socket.c Wed Jan 16 11:16:29 2002
+++ linux/net/socket.c Thu Jan 17 14:29:59 2002
@@ -437,11 +437,11 @@
struct inode * inode;
struct socket * sock;
- inode = get_empty_inode();
+ inode = new_inode(sock_mnt->mnt_sb);
if (!inode)
return NULL;
- inode->i_sb = sock_mnt->mnt_sb;
+ inode->i_dev = NODEV;
sock = socki_lookup(inode);
inode->i_mode = S_IFSOCK|S_IRWXUGO;
diff -u --recursive --new-file pre1/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- pre1/linux/net/sunrpc/sched.c Mon Jan 14 10:10:43 2002
+++ linux/net/sunrpc/sched.c Tue Jan 15 13:53:51 2002
@@ -721,7 +721,7 @@
__rpc_execute(task);
- if (++count >= 200 || current->need_resched) {
+ if (++count >= 200 || need_resched()) {
count = 0;
schedule();
}