From 2470b27dca42284f9e527466575417058391a5c3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:17:10 -0500 Subject: [PATCH] Linux 2.1.127 Ok, after two fairly hectic weeks for me, 2.1.127 is finally out there. This kernel does: - various small but important networking fixes from Davem (thanks). One of them is the "anti-nagle" bit to allow programs that know what they are doing to avoid nagling by telling the kernel so. This is mainly things like Web servers and ftp-servers that can use this option together with "sendfile()". - scheduling timeout interface change: the new interface is much more logical than the old one, and allows us to get the jiffies wrap-around case right. Thanks to Andrea Arcangeli. - Various driver updates: specialix, sonycd, - Memory management fixups. Handle out-of-memory conditions correctly, and handle high memory load much more gracefully. - sparc and PowerPC architecture updates - 3c509 SMP fix, tlan PCI probe update. - scsi driver updates: ncr53c8xx, aic7xxx, dc390 - filesystem updates: autofs, hfs, umsdos Go, test, be happy, Linus --- Documentation/Configure.help | 8 +- arch/alpha/kernel/osf_sys.c | 12 +-- arch/i386/defconfig | 2 +- arch/m68k/atari/time.c | 3 +- arch/mips/kernel/irixsig.c | 10 +- arch/mips/kernel/sysirix.c | 9 +- arch/ppc/8xx_io/uart.c | 9 +- drivers/block/floppy.c | 4 +- drivers/block/paride/pcd.c | 3 +- drivers/block/paride/pf.c | 3 +- drivers/block/paride/pg.c | 3 +- drivers/block/paride/pt.c | 3 +- drivers/block/swim3.c | 9 +- drivers/cdrom/cdu31a.c | 9 +- drivers/cdrom/mcd.c | 3 +- drivers/cdrom/mcdx.c | 9 +- drivers/cdrom/sbpcd.c | 3 +- drivers/cdrom/sonycd535.c | 67 ++++++------ drivers/char/ftape/lowlevel/fdc-io.c | 10 +- drivers/char/ftape/lowlevel/ftape-io.c | 7 +- drivers/char/lp.c | 139 +++++++++---------------- drivers/char/pc_keyb.c | 8 ++ drivers/char/pcxx.c | 3 +- drivers/char/radio-sf16fmi.c | 6 +- drivers/char/riscom8.c | 6 +- drivers/char/rocket.c | 9 +- drivers/char/saa5249.c | 3 +- drivers/char/serial167.c | 3 +- drivers/char/specialix.c | 6 +- drivers/char/stallion.c | 3 +- drivers/char/tpqic02.c | 5 +- drivers/isdn/act2000/act2000_isa.c | 3 +- drivers/isdn/avmb1/b1capi.c | 3 +- drivers/isdn/hisax/arcofi.c | 3 +- drivers/isdn/hisax/asuscom.c | 6 +- drivers/isdn/hisax/diva.c | 6 +- drivers/isdn/hisax/elsa.c | 9 +- drivers/isdn/hisax/netjet.c | 6 +- drivers/isdn/hisax/sedlbauer.c | 6 +- drivers/isdn/hisax/sportster.c | 6 +- drivers/isdn/hisax/teleint.c | 6 +- drivers/isdn/hisax/teles3c.c | 9 +- drivers/isdn/icn/icn.c | 18 ++-- drivers/isdn/sc/init.c | 12 +-- drivers/isdn/sc/message.c | 3 +- drivers/macintosh/macserial.c | 6 +- drivers/macintosh/mediabay.c | 3 +- drivers/net/cs89x0.c | 3 +- drivers/net/sktr.c | 7 +- drivers/pnp/parport_probe.c | 6 +- drivers/sbus/char/pcikbd.c | 3 +- drivers/sbus/char/sab82532.c | 6 +- drivers/sbus/char/su.c | 6 +- drivers/sbus/char/zs.c | 6 +- drivers/scsi/Config.in | 2 +- drivers/scsi/aic7xxx.c | 35 +++++-- drivers/sgi/char/sgiserial.c | 6 +- drivers/sound/cs4232.c | 4 +- drivers/sound/dmabuf.c | 4 +- drivers/sound/dmasound.c | 3 +- drivers/sound/es1370.c | 15 +-- drivers/sound/es1371.c | 15 +-- drivers/sound/gus_wave.c | 5 +- drivers/sound/maui.c | 4 +- drivers/sound/msnd_pinnacle.c | 24 ++--- drivers/sound/sgalaxy.c | 4 +- drivers/sound/sonicvibes.c | 10 +- drivers/sound/wavfront.c | 8 +- fs/namei.c | 2 +- fs/ncpfs/sock.c | 12 +-- fs/nfsd/vfs.c | 3 +- fs/umsdos/README-WIP.txt | 42 ++++---- fs/umsdos/check.c | 2 + fs/umsdos/dir.c | 10 +- fs/umsdos/inode.c | 18 ++-- fs/umsdos/namei.c | 2 +- fs/umsdos/rdir.c | 4 +- include/linux/if.h | 2 +- include/linux/lp.h | 12 ++- include/linux/mm.h | 1 - include/linux/socket.h | 1 + include/net/tcp.h | 26 +++-- init/main.c | 4 +- kernel/sched.c | 1 - kernel/sysctl.c | 4 +- mm/memory.c | 65 ++++++------ mm/slab.c | 2 +- mm/vmscan.c | 10 +- net/appletalk/ddp.c | 3 +- net/core/dev.c | 2 +- net/core/sock.c | 17 +-- net/core/sysctl_net_core.c | 2 +- net/ipv4/arp.c | 6 +- net/ipv4/ip_masq.c | 11 +- net/ipv4/tcp.c | 101 ++++++++++++------ net/ipv4/tcp_input.c | 27 ++--- net/ipv4/tcp_ipv4.c | 6 +- net/ipv4/tcp_output.c | 4 +- net/ipv4/tcp_timer.c | 21 ++-- net/ipv4/timer.c | 10 +- net/ipv6/tcp_ipv6.c | 6 +- net/netlink/af_netlink.c | 6 +- 102 files changed, 514 insertions(+), 589 deletions(-) diff --git a/Documentation/Configure.help b/Documentation/Configure.help index d546aa920e00..ad33d3161478 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -7246,10 +7246,10 @@ CONFIG_RISCOM8 Specialix IO8+ card support CONFIG_SPECIALIX - This is a driver for the Specialix IO8+ multiport card which gives - you many serial ports. You would need something like this to - connect more than two modems to your Linux box, for instance in - order to become a BBS. + This is a driver for the Specialix IO8+ multiport card (both the + ISA and the PCI version) which gives you many serial ports. You + would need something like this to connect more than two modems to + your Linux box, for instance in order to become a BBS. If you have a card like that, say Y here and read the file Documentation/specialix.txt. Also it's possible to say M here and diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index eea674aa68ef..00e02d8a1633 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1306,6 +1306,7 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema { struct timeval tmp; unsigned long ticks; + unsigned long tmp_timeout; if (get_tv32(&tmp, sleep)) goto fault; @@ -1313,18 +1314,11 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema ticks = tmp.tv_usec; ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ); ticks += tmp.tv_sec * HZ; - current->timeout = ticks + jiffies; - current->state = TASK_INTERRUPTIBLE; - schedule(); + current->state = TASK_INTERRUPTIBLE; + ticks = schedule_timeout(ticks); if (remain) { - ticks = jiffies; - if (ticks < current->timeout) - ticks = current->timeout - ticks; - else - ticks = 0; - current->timeout = 0; tmp.tv_sec = ticks / HZ; tmp.tv_usec = ticks % HZ; if (put_tv32(remain, &tmp)) diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 484084e5099f..9fadb16d5934 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -157,7 +157,7 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set CONFIG_SCSI_NCR53C8XX=y -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index 79c4f48f2e62..0fd3795a5360 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -279,8 +279,7 @@ int atari_tt_hwclk( int op, struct hwclk_time *t ) while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HWCLK_POLL_INTERVAL; - schedule(); + schedule_timeout(HWCLK_POLL_INTERVAL); } save_flags(flags); diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index d0e286def792..86a9a5c72e74 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -568,7 +568,7 @@ static inline unsigned long timespectojiffies(struct timespec *value) asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, struct timespec *tp) { - unsigned long expire = 0; + long expire = MAX_SCHEDULE_TIMEOUT; sigset_t kset; int i, sig, error, timeo = 0; @@ -603,21 +603,21 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, error = -EINVAL; goto out; } - expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec)+jiffies; - current->timeout = expire; + expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec); } while(1) { long tmp = 0; - current->state = TASK_INTERRUPTIBLE; schedule(); + current->state = TASK_INTERRUPTIBLE; + expire = schedule_timeout(expire); for (i=0; i<=4; i++) tmp |= (current->signal.sig[i] & kset.sig[i]); if (tmp) break; - if (tp && expire <= jiffies) { + if (!expire) { timeo = 1; break; } diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index d1c2da72a0be..c474c65ccc05 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -1081,13 +1081,8 @@ out: asmlinkage int irix_sginap(int ticks) { - lock_kernel(); - if(ticks) { - current->timeout = ticks + jiffies; - current->state = TASK_INTERRUPTIBLE; - } - schedule(); - unlock_kernel(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(ticks); return 0; } diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c index bb1a5699c05b..fdbd0c79693f 100644 --- a/arch/ppc/8xx_io/uart.c +++ b/arch/ppc/8xx_io/uart.c @@ -1314,12 +1314,11 @@ static void end_break(ser_info_t *info) static void send_break(ser_info_t *info, int duration) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; #ifdef SERIAL_DEBUG_SEND_BREAK printk("rs_send_break(%d) jiff=%lu...", duration, jiffies); #endif begin_break(info); - schedule(); + schedule_timeout(duration); end_break(info); #ifdef SERIAL_DEBUG_SEND_BREAK printk("done jiffies=%lu\n", jiffies); @@ -1633,8 +1632,7 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } @@ -1691,8 +1689,7 @@ static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout) #endif current->state = TASK_INTERRUPTIBLE; /* current->counter = 0; make us low-priority */ - current->timeout = jiffies + char_time; - schedule(); + schedule_timeout(char_time); if (signal_pending(current)) break; if (timeout && ((orig_jiffies + timeout) < jiffies)) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index cf47e47909a5..f958d62a00ff 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1740,12 +1740,14 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(do_print) print_result("unexpected interrupt", inr); if (inr == 0){ + int max_sensei = 4; do { output_byte(FD_SENSEI); inr = result(); if(do_print) print_result("sensei", inr); - } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2); + max_sensei--; + } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei); } if (handler) { int cpu = smp_processor_id(); diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 48055268c573..6366afa6ba3c 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -559,8 +559,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position) static void pcd_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pcd_reset( int unit ) diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index a6418efa7baf..255352f0ab5f 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -660,8 +660,7 @@ static void pf_eject( int unit ) static void pf_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 128b2a2e5804..1563a2afc185 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -357,8 +357,7 @@ void cleanup_module(void) static void pg_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pg_wait( int unit, int go, int stop, int tmo, char * msg ) diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 48fcdda747af..1a09c84b09d6 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -464,8 +464,7 @@ static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) static void pt_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pt_poll_dsc( int unit, int pause, int tmo, char *msg ) diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index bacb3df9800f..fad28716ce3c 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -740,8 +740,7 @@ static int fd_eject(struct floppy_state *fs) break; } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } fs->ejected = 1; release_drive(fs); @@ -807,8 +806,7 @@ static int floppy_open(struct inode *inode, struct file *filp) break; } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0)) @@ -911,8 +909,7 @@ static int floppy_revalidate(kdev_t dev) if (signal_pending(current)) break; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } ret = swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0; diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index cd28f5d4039d..7bafb457a860 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -409,8 +409,7 @@ sony_sleep(void) if (cdu31a_irq <= 0) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies; - schedule(); + schedule_timeout(0); } else /* Interrupt driven */ { @@ -753,8 +752,7 @@ restart_on_error(void) } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 2*HZ; - schedule(); + schedule_timeout(2*HZ); sony_get_toc(); } @@ -1012,8 +1010,7 @@ retry_cd_operation: { num_retries++; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ/10; /* Wait .1 seconds on retries */ - schedule(); + schedule_timeout(HZ/10); /* Wait .1 seconds on retries */ goto retry_cd_operation; } diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index 46866f4c2663..b69f9e834f7a 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -1100,8 +1100,7 @@ static int mcd_open(struct cdrom_device_info * cdi, int purpose) return -EIO; /* drive doesn't respond */ if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ; - schedule(); + schedule_timeout(HZ); } } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index d27417be6ec9..60845a3cb948 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -794,8 +794,7 @@ static void mcdx_delay(struct s_drive_stuff *stuff, long jifs) * allowed! */ if (current->pid == 0) { while (jiffies < tout) { - current->timeout = jiffies; - schedule(); + schedule_timeout(0); } } else { current->timeout = tout; @@ -1247,6 +1246,7 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp, { int border; int done = 0; + long timeout; if (stuffp->audio) { xwarn("Attempt to read from audio CD.\n"); @@ -1281,13 +1281,12 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp, do { - current->timeout = jiffies + 5 * HZ; while (stuffp->busy) { - interruptible_sleep_on(&stuffp->busyq); + timeout = interruptible_sleep_on_timeout(&stuffp->busyq, 5*HZ); if (!stuffp->introk) { xtrace(XFER, "error via interrupt\n"); } - else if (current->timeout == 0) { xtrace(XFER, "timeout\n"); } + else if (!timeout) { xtrace(XFER, "timeout\n"); } else if (signal_pending(current)) { xtrace(XFER, "signal\n"); } else continue; diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index de9009a8c0a1..8c7592146e6f 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -843,8 +843,7 @@ static void sbp_sleep(u_int time) { sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + time; - schedule(); + schedule_timeout(time); sti(); } /*==========================================================================*/ diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index aaad43c966ed..f9a321b6f20f 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -62,26 +62,24 @@ * This interface is (unfortunately) a polled interface. This is * because most Sony interfaces are set up with DMA and interrupts * disables. Some (like mine) do not even have the capability to - * handle interrupts or DMA. For this reason you will see a lot of + * handle interrupts or DMA. For this reason you will see a bit of * the following: * - * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT; - * while ((retry_count > jiffies) && (! state = TASK_INTERRUPTIBLE; - current->timeout = jiffies; - schedule(); + schedule_timeout(0); } else { /* Interrupt driven */ cli(); enable_interrupts(); @@ -370,12 +365,13 @@ select_unit(int unit_no) static int read_result_reg(Byte *data_ptr) { - int retry_count; + unsigned long snap; int read_status; - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (jiffies < retry_count) { - if (((read_status = inb(read_status_reg)) & SONY535_RESULT_NOT_READY_BIT) == 0) { + snap = jiffies; + while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { + read_status = inb(read_status_reg); + if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) { #if DEBUG > 1 printk(CDU535_MESSAGE_NAME ": read_result_reg(): readStatReg = 0x%x\n", read_status); @@ -599,7 +595,7 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], Byte cmd_buff[7]; int i; int read_status; - int retry_count; + unsigned long snap; Byte *data_buff; int sector_count = 0; @@ -618,8 +614,9 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], /* read back the data one block at a time */ while (0 < n_blocks--) { /* wait for data to be ready */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (jiffies < retry_count) { + int data_valid = 0; + snap = jiffies; + while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { read_status = inb(read_status_reg); if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) { read_exec_status(status); @@ -630,11 +627,12 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], data_buff = buff[sector_count++]; for (i = 0; i < block_size; i++) *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */ + data_valid = 1; break; /* exit the timeout loop */ } sony_sleep(); /* data not ready, sleep a while */ } - if (retry_count <= jiffies) + if (!data_valid) return TIME_OUT; /* if we reach this stage */ } @@ -893,8 +891,7 @@ do_cdu535_request(void) if (readStatus == BAD_STATUS) { /* Sleep for a while, then retry */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + RETRY_FOR_BAD_STATUS; - schedule(); + schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10); } #if DEBUG > 0 printk(CDU535_MESSAGE_NAME @@ -1493,7 +1490,8 @@ sony535_init(void)) Byte cmd_buff[3]; Byte ret_buff[2]; Byte status[2]; - int retry_count; + unsigned long snap; + int got_result = 0; int tmp_irq; int i; @@ -1525,21 +1523,22 @@ sony535_init(void)) } /* look for the CD-ROM, follows the procedure in the DOS driver */ inb(select_unit_reg); - retry_count = jiffies + 2 * HZ; - while (jiffies < retry_count) - sony_sleep(); /* wait for 40 18 Hz ticks (from DOS driver) */ + /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */ + schedule_timeout((HZ+17)*40/18); inb(result_reg); outb(0, read_status_reg); /* does a reset? */ - retry_count = jiffies + SONY_JIFFIES_TIMEOUT; - while (jiffies < retry_count) { + snap = jiffies; + while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { select_unit(0); - if (inb(result_reg) != 0xff) + if (inb(result_reg) != 0xff) { + got_result = 1; break; + } sony_sleep(); } - if ((jiffies < retry_count) && (check_drive_status() != TIME_OUT)) { + if (got_result && (check_drive_status() != TIME_OUT)) { /* CD-ROM drive responded -- get the drive configuration */ cmd_buff[0] = SONY535_INQUIRY; if (do_sony_cmd(cmd_buff, 1, status, diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c index 5441daee9706..c126d05a8384 100644 --- a/drivers/char/ftape/lowlevel/fdc-io.c +++ b/drivers/char/ftape/lowlevel/fdc-io.c @@ -389,6 +389,7 @@ int fdc_interrupt_wait(unsigned int time) sigset_t old_sigmask; static int resetting = 0; TRACE_FUN(ft_t_fdc_dma); + long timeout; #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16) if (waitqueue_active(&ftape_wait_intr)) { @@ -400,8 +401,7 @@ int fdc_interrupt_wait(unsigned int time) } #endif /* timeout time will be up to USPT microseconds too long ! */ - current->timeout = jiffies + (1000 * time + FT_USPT - 1) / FT_USPT; - current->state = TASK_INTERRUPTIBLE; + timeout = (1000 * time + FT_USPT - 1) / FT_USPT; spin_lock_irq(¤t->sigmask_lock); old_sigmask = current->blocked; @@ -409,9 +409,10 @@ int fdc_interrupt_wait(unsigned int time) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); + current->state = TASK_INTERRUPTIBLE; add_wait_queue(&ftape_wait_intr, &wait); - while (!ft_interrupt_seen && current->state != TASK_RUNNING) { - schedule(); /* sets TASK_RUNNING on timeout */ + while (!ft_interrupt_seen && (current->state == TASK_INTERRUPTIBLE)) { + timeout = schedule_timeout(timeout); } spin_lock_irq(¤t->sigmask_lock); @@ -433,7 +434,6 @@ int fdc_interrupt_wait(unsigned int time) */ current->state = TASK_RUNNING; if (ft_interrupt_seen) { /* woken up by interrupt */ - current->timeout = 0; /* interrupt hasn't cleared this */ ft_interrupt_seen = 0; TRACE_EXIT 0; } diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c index e43da1e27a16..2fda1578b44f 100644 --- a/drivers/char/ftape/lowlevel/ftape-io.c +++ b/drivers/char/ftape/lowlevel/ftape-io.c @@ -89,17 +89,18 @@ void ftape_sleep(unsigned int time) /* Time too small for scheduler, do a busy wait ! */ ftape_udelay(time); } else { + long timeout; unsigned long flags; unsigned int ticks = (time + FT_USPT - 1) / FT_USPT; TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks); - current->timeout = jiffies + ticks; + timeout = ticks; current->state = TASK_INTERRUPTIBLE; save_flags(flags); sti(); do { while (current->state != TASK_RUNNING) { - schedule(); + timeout = schedule_timeout(timeout); } /* Mmm. Isn't current->blocked == 0xffffffff ? */ @@ -108,7 +109,7 @@ void ftape_sleep(unsigned int time) "awoken by non-blocked signal :-("); break; /* exit on signal */ } - } while (current->timeout > 0); + } while (timeout); restore_flags(flags); } TRACE_EXIT; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index a1f60057e391..baec5e4cb11d 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -16,14 +16,8 @@ * Parport sharing hacking by Andrea Arcangeli * Fixed kernel_(to/from)_user memory copy to check for errors * by Riccardo Facchetti - * Redesigned interrupt handling for handle printers with buggy handshake - * by Andrea Arcangeli, 11 May 1998 - * Full efficient handling of printer with buggy irq handshake (now I have - * understood the meaning of the strange handshake). This is done sending new - * characters if the interrupt is just happened, even if the printer say to - * be still BUSY. This is needed at least with Epson Stylus Color. - * I also fixed the irq on the rising edge of the strobe problem. - * Andrea Arcangeli, 15 Oct 1998 + * Interrupt handling workaround for printers with buggy handshake + * by Andrea Arcangeli, 11 May 98 */ /* This driver should, in theory, work with any parallel port that has an @@ -84,14 +78,7 @@ * * ftp://e-mind.com/pub/linux/pscan/ * - * My printer scanner run on an Epson Stylus Color show that such printer - * generates the irq on the _rising_ edge of the STROBE. Now lp handle - * this case fine too. - * - * I also understood that on such printer we are just allowed to send - * new characters after the interrupt even if the BUSY line is still active. - * - * 15 Oct 1998, Andrea Arcangeli + * 11 May 98, Andrea Arcangeli */ #include @@ -108,6 +95,7 @@ #include #undef LP_STATS +#undef LP_NEED_CAREFUL #include #include @@ -127,21 +115,16 @@ struct lp_struct lp_table[LP_NO] = NULL, 0, 0, 0} }; -/* - * Test if printer is ready. - */ -#define LP_READY(status) \ +/* Test if printer is ready (and optionally has no error conditions) */ +#ifdef LP_NEED_CAREFUL +#define LP_READY(minor, status) \ + ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY)) +#define _LP_CAREFUL_READY(status) \ ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \ (LP_PBUSY|LP_PSELECD|LP_PERRORP) - -/* - * Test if the printer has error conditions. - */ -#define LP_NO_ERROR(status) \ - ((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \ - (LP_PSELECD|LP_PERRORP) - -#define LP_NO_ACKING(status) ((status) & LP_PACK) +#else +#define LP_READY(minor, status) ((status) & LP_PBUSY) +#endif #undef LP_DEBUG #undef LP_READ_DEBUG @@ -189,7 +172,7 @@ static __inline__ void lp_schedule(int minor, long timeout) schedule_timeout(timeout); lp_parport_claim(minor); } else - schedule(); + schedule_timeout(timeout); } static int lp_reset(int minor) @@ -204,81 +187,52 @@ static int lp_reset(int minor) return retval; } -static inline void lp_wait(int minor) -{ - udelay(LP_WAIT(minor)); -} - static inline int lp_char(char lpchar, int minor) { + unsigned int wait = 0; unsigned long count = 0; #ifdef LP_STATS struct lp_stats *stats; #endif - if (signal_pending(current)) - return 0; - for (;;) { - unsigned char status; lp_yield(minor); - - status = r_str(minor); - /* - * On Epson Stylus Color we must continue even if LP_READY() - * is false to be efficient. This way is backwards - * compatible with old not-buggy printers. -arca - */ - if (LP_NO_ERROR(status) && - ((lp_table[minor].irq_detected && LP_NO_ACKING(status)) || - LP_READY(status))) + if (LP_READY(minor, r_str(minor))) break; - /* - * To have a chance to sleep on the interrupt we should break - * the polling loop ASAP. Unfortunately there seems to be - * some hardware that underperform so we leave this - * configurable at runtime. So when printing with irqs - * `tunelp /dev/lp0 -c 1' is a must to take the full - * advantage of the irq. -arca - */ - if (++count == LP_CHAR(minor)) - return 0; + if (++count == LP_CHAR(minor) || signal_pending(current)) + return 0; } w_dtr(minor, lpchar); - #ifdef LP_STATS stats = &LP_STAT(minor); stats->chars++; #endif - - /* - * Epson Stylus Color generate the IRQ on the rising edge of - * strobe so clean the irq's information before playing with - * the strobe. -arca - */ - lp_table[minor].irq_detected = 0; - lp_table[minor].irq_missed = 0; - /* - * Be sure that the CPU doesn' t reorder instruction. I am not sure - * if it' s needed also before an outb(). If not tell me ;-). -arca - */ - mb(); - /* must wait before taking strobe high, and after taking strobe low, according spec. Some printers need it, others don't. */ - lp_wait(minor); - +#ifndef __sparc__ + while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */ + wait++; +#else + udelay(1); +#endif /* control port takes strobe high */ + w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE); +#ifndef __sparc__ + while (wait) /* FIXME: should be a udelay() */ + wait--; +#else + udelay(1); +#endif + /* take strobe low */ if (LP_POLLED(minor)) - { - w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE); - lp_wait(minor); + /* take strobe low */ w_ctr(minor, LP_PSELECP | LP_PINITP); - } else { - w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN); - lp_wait(minor); + else + { + lp_table[minor].irq_detected = 0; + lp_table[minor].irq_missed = 0; w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN); } @@ -286,8 +240,7 @@ static inline int lp_char(char lpchar, int minor) /* update waittime statistics */ if (count > stats->maxwait) { #ifdef LP_DEBUG - printk(KERN_DEBUG "lp%d success after %d counts.\n", - minor, count); + printk(KERN_DEBUG "lp%d success after %d counts.\n", minor, count); #endif stats->maxwait = count; } @@ -371,12 +324,8 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count) lp_table[minor].last_error = 0; lp_table[minor].irq_detected = 0; lp_table[minor].irq_missed = 1; - LP_POLLED(minor) = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE; - if (LP_POLLED(minor)) - w_ctr(minor, LP_PSELECP | LP_PINITP); - else - w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN); + w_ctr(minor, LP_PSELECP | LP_PINITP); do { bytes_written = 0; @@ -431,7 +380,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count) printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp->runchars, LP_TIME(minor)); #endif current->state = TASK_INTERRUPTIBLE; - lp_schedule (minor, LP_TIME(minor)); + lp_schedule(minor, LP_TIME(minor)); } else { cli(); if (LP_PREEMPTED(minor)) @@ -447,7 +396,9 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count) goto lp_polling; } if (!lp_table[minor].irq_detected) + { interruptible_sleep_on_timeout(&lp->wait_q, LP_TIMEOUT_INTERRUPT); + } sti(); } } @@ -694,6 +645,14 @@ static int lp_ioctl(struct inode *inode, struct file *file, else LP_F(minor) &= ~LP_ABORTOPEN; break; +#ifdef LP_NEED_CAREFUL + case LPCAREFUL: + if (arg) + LP_F(minor) |= LP_CAREFUL; + else + LP_F(minor) &= ~LP_CAREFUL; + break; +#endif case LPWAIT: LP_WAIT(minor) = arg; break; diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c index 797aa3b325e8..c5a5f15c9128 100644 --- a/drivers/char/pc_keyb.c +++ b/drivers/char/pc_keyb.c @@ -904,10 +904,18 @@ static struct miscdevice psaux_mouse = { static int __init psaux_init(void) { +#if 0 + /* + * Don't bother with the BIOS flag: even if we don't have + * a mouse connected at bootup we may still want to connect + * one later, and we don't want to just let the BIOS tell + * us that it has no mouse.. + */ if (aux_device_present != 0xaa) return -EIO; printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n"); +#endif misc_register(&psaux_mouse); queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); memset(queue, 0, sizeof(*queue)); diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 9fe8bcc2364d..b1c1bb3e3bd8 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -633,8 +633,7 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp) if(info->blocked_open) { if(info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c index f82166b16e31..9872e59511f0 100644 --- a/drivers/char/radio-sf16fmi.c +++ b/drivers/char/radio-sf16fmi.c @@ -82,8 +82,7 @@ static inline int fmi_setfreq(struct fmi_device *dev, unsigned long freq) outbits(8, 0xC0, myport); /* it is better than udelay(140000), isn't it? */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ/7; - schedule(); + schedule_timeout(HZ/7); /* ignore signals, we really should restore volume */ if (dev->curvol) fmi_unmute(myport); return 0; @@ -100,8 +99,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) outb(val | 0x10, myport); /* it is better than udelay(140000), isn't it? */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ/7; - schedule(); + schedule_timeout(HZ/7); /* do not do it..., 140ms is very looong time to get signal in real program if (signal_pending(current)) return -EINTR; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index b854fa338049..7da0fa512408 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1172,8 +1172,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp) timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + port->timeout; - schedule(); + schedule_timeout(port->timeout); if (jiffies > timeout) break; } @@ -1189,8 +1188,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp) if (port->blocked_open) { if (port->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + port->close_delay; - schedule(); + schedule_timeout(port->close_delay); } wake_up_interruptible(&port->open_wait); } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index c661f8238154..9dff48416efd 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1181,8 +1181,7 @@ static void rp_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } else { @@ -1269,10 +1268,9 @@ static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios) static void send_break( struct r_port * info, int duration) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; cli(); sSendBreak(&info->channel); - schedule(); + schedule_timeout(duration); sClrBreak(&info->channel); sti(); } @@ -1666,8 +1664,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) #endif current->state = TASK_INTERRUPTIBLE; current->counter = 0; /* make us low-priority */ - current->timeout = jiffies + check_time; - schedule(); + schedule_timeout(check_time); if (signal_pending(current)) break; } diff --git a/drivers/char/saa5249.c b/drivers/char/saa5249.c index 608ac56ba670..27c7d4c18795 100644 --- a/drivers/char/saa5249.c +++ b/drivers/char/saa5249.c @@ -242,8 +242,7 @@ static void jdelay(unsigned long delay) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + delay; - schedule(); + schedule_timeout(delay); spin_lock_irq(¤t->sigmask_lock); current->blocked = oldblocked; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 9932e22c73a8..b3ff152579f6 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1952,8 +1952,7 @@ cy_close(struct tty_struct * tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index de66c1581d4e..72d1f6276011 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1551,8 +1551,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + port->timeout; - schedule(); + schedule_timeout(port->timeout); if (jiffies > timeout) { printk (KERN_INFO "Timeout waiting for close\n"); break; @@ -1571,8 +1570,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) if (port->blocked_open) { if (port->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + port->close_delay; - schedule(); + schedule_timeout(port->close_delay); } wake_up_interruptible(&port->open_wait); } diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 8fb7490b987f..0b2f495b1849 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1072,8 +1072,7 @@ static void stl_delay(int len) #endif if (len > 0) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + len; - schedule(); + schedule_timeout(len); current->state = TASK_RUNNING; } } diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index 35deb815bb4d..4878d877efc7 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -588,9 +588,10 @@ static int wait_for_ready(time_t timeout) /* not ready and no exception && timeout not expired yet */ while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (jiffiestimeout = jiffies + 3*HZ/10; /* nap 0.30 sec between checks, */ current->state = TASK_INTERRUPTIBLE; - schedule(); /* but could be woken up earlier by signals... */ + /* nap 0.30 sec between checks, */ + /* but could be woken up earlier by signals... */ + schedule_timeout(3*HZ/10); } /* don't use jiffies for this test because it may have changed by now */ diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c index 76d2b3a6aa8a..d19ff99e4720 100644 --- a/drivers/isdn/act2000/act2000_isa.c +++ b/drivers/isdn/act2000/act2000_isa.c @@ -61,8 +61,7 @@ isa_delay(long t) { sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + t; - schedule(); + schedule_timeout(t); sti(); } diff --git a/drivers/isdn/avmb1/b1capi.c b/drivers/isdn/avmb1/b1capi.c index 648f19fc2372..dbf3606f4cee 100644 --- a/drivers/isdn/avmb1/b1capi.c +++ b/drivers/isdn/avmb1/b1capi.c @@ -965,9 +965,8 @@ static int capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate != CARD_RUNNING) { - current->timeout = jiffies + HZ / 10; /* 0.1 sec */ current->state = TASK_INTERRUPTIBLE; - schedule(); + schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c index dad1711c3bd3..1717b3a278ec 100644 --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -40,8 +40,7 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg) { while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) { cnt--; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ } restore_flags(flags); sprintf(tmp, "arcofi tout %d", cnt); diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c index c8491744642e..6980a2888685 100644 --- a/drivers/isdn/hisax/asuscom.c +++ b/drivers/isdn/hisax/asuscom.c @@ -201,12 +201,10 @@ reset_asuscom(struct IsdnCardState *cs) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); byteout(cs->hw.asus.adr, 0); /* Reset Off */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); restore_flags(flags); } diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index fa3a45b72d35..a533272c86d4 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -241,13 +241,11 @@ reset_diva(struct IsdnCardState *cs) cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ if (cs->subtyp == DIVA_ISA) cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; else diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 6a9966431637..00817806590d 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -450,12 +450,10 @@ reset_elsa(struct IsdnCardState *cs) sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); schedule(); restore_flags(flags); @@ -658,8 +656,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) } else return(0); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (110 * HZ) / 1000; /* Timeout 110ms */ - schedule(); + schedule_timeout((110*HZ)/1000); /* Timeout 110ms */ restore_flags(flags); cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 0686598e20a0..54f9c14d8fec 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -971,13 +971,11 @@ reset_netjet(struct IsdnCardState *cs) cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); cs->hw.njet.auxd = 0; cs->hw.njet.dmactrl = 0; diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 40dc8e622a04..46d3edaf05b6 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -242,12 +242,10 @@ reset_sedlbauer(struct IsdnCardState *cs) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); restore_flags(flags); } } diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c index cb867a13fa3d..43d0641da357 100644 --- a/drivers/isdn/hisax/sportster.c +++ b/drivers/isdn/hisax/sportster.c @@ -165,13 +165,11 @@ reset_sportster(struct IsdnCardState *cs) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); restore_flags(flags); } diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c index d86dd79a40f6..f7e38253bf59 100644 --- a/drivers/isdn/hisax/teleint.c +++ b/drivers/isdn/hisax/teleint.c @@ -246,13 +246,11 @@ reset_TeleInt(struct IsdnCardState *cs) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 3; - schedule(); + schedule_timeout(3); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); restore_flags(flags); } diff --git a/drivers/isdn/hisax/teles3c.c b/drivers/isdn/hisax/teles3c.c index 848c46be9ac8..3042f7139dd3 100644 --- a/drivers/isdn/hisax/teles3c.c +++ b/drivers/isdn/hisax/teles3c.c @@ -79,13 +79,11 @@ reset_t163c(struct IsdnCardState *cs) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 3; - schedule(); + schedule_timeout(3); cs->hw.hfcD.cirm = HFCD_MEM8K; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); cs->hw.hfcD.cirm |= HFCD_INTB; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* INT B */ cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); @@ -136,8 +134,7 @@ t163c_card_msg(struct IsdnCardState *cs, int mt, void *arg) save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (80*HZ)/1000; - schedule(); + schedule_timeout((80*HZ)/1000); cs->hw.hfcD.ctmt |= HFCD_TIM800; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 15c767b43a05..fe5737344602 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -914,8 +914,7 @@ icn_check_loader(int cardnumber) printk(KERN_DEBUG "Loader %d TO?\n", cardnumber); #endif current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + ICN_BOOT_TIMEOUT1; - schedule(); + schedule_timeout(ICN_BOOT_TIMEOUT1); } else { #ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d OK\n", cardnumber); @@ -941,8 +940,7 @@ int slsec = sec; \ printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \ while (slsec) { \ current->state = TASK_INTERRUPTIBLE; \ - current->timeout = jiffies + HZ; \ - schedule(); \ + schedule_timeout(HZ); \ slsec--; \ } \ } @@ -1104,8 +1102,7 @@ icn_loadproto(u_char * buffer, icn_card * card) return -EIO; } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 10; - schedule(); + schedule_timeout(10); } } writeb(0x20, &sbuf_n); @@ -1129,8 +1126,7 @@ icn_loadproto(u_char * buffer, icn_card * card) printk(KERN_DEBUG "Proto TO?\n"); #endif current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + ICN_BOOT_TIMEOUT1; - schedule(); + schedule_timeout(ICN_BOOT_TIMEOUT1); } else { if ((card->secondhalf) || (!card->doubleS0)) { #ifdef BOOT_DEBUG @@ -1425,11 +1421,9 @@ icn_command(isdn_ctrl * c, icn_card * card) if (!card->leased) { card->leased = 1; while (card->ptype == ISDN_PTYPE_UNKNOWN) { - current->timeout = jiffies + ICN_BOOT_TIMEOUT1; - schedule(); + schedule_timeout(ICN_BOOT_TIMEOUT1); } - current->timeout = jiffies + ICN_BOOT_TIMEOUT1; - schedule(); + schedule_timeout(ICN_BOOT_TIMEOUT1); sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", (a & 1)?'1':'C', (a & 2)?'2':'C'); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index d34dd03b9f88..788950eebf5a 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -165,8 +165,7 @@ int init_sc(void) pr_debug("Doing a SAFE probe reset\n"); outb(0xFF, io[b] + RESET_OFFSET); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + milliseconds(10000); - schedule(); + schedule_timeout(milliseconds(10000)); } pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], ram[b] == 0 ? "will" : "won't"); @@ -514,8 +513,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) */ outb(PRI_BASEPG_VAL, pgport); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ; - schedule(); + schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); #if 0 @@ -535,8 +533,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) */ outb(BRI_BASEPG_VAL, pgport); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ; - schedule(); + schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); #if 0 @@ -571,8 +568,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) x = 0; while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); x++; } if(x == 100) { diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index 2cbdcdae895e..628cdc80396f 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -267,8 +267,7 @@ int send_and_receive(int card, /* wait for the response */ while (tries < timeout) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); pr_debug("SAR waiting..\n"); diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index 7c8cf23d8db5..0178b6ebb765 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -1264,8 +1264,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } @@ -1301,8 +1300,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { current->state = TASK_INTERRUPTIBLE; current->counter = 0; /* make us low-priority */ - current->timeout = jiffies + char_time; - schedule(); + schedule_timeout(char_time); if (signal_pending(current)) break; if (timeout && ((orig_jiffies + timeout) < jiffies)) diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 53f7ab62e7ba..90490bb512c4 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -184,8 +184,7 @@ media_bay_task(void *x) prev = media_bay_id; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); if (signal_pending(current)) return 0; } diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index e83c8faf96aa..a5e0c68b27b0 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -403,8 +403,7 @@ reset_chip(struct device *dev)) /* wait 30 ms */ current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 3; - schedule(); + schedule_timeout(30*HZ/1000); if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ diff --git a/drivers/net/sktr.c b/drivers/net/sktr.c index a01000f88c9c..f86acd1fbef9 100644 --- a/drivers/net/sktr.c +++ b/drivers/net/sktr.c @@ -1526,12 +1526,11 @@ static void sktr_wait(unsigned long time) { long tmp; - tmp = jiffies + time/(1000000/HZ); + tmp = time/(1000000/HZ); do { - current->timeout = tmp; current->state = TASK_INTERRUPTIBLE; - schedule(); - } while(tmp > jiffies); + tmp = schedule_timeout(tmp); + } while(tmp); return; } diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c index 97a824fd32ca..32188af9e737 100644 --- a/drivers/pnp/parport_probe.c +++ b/drivers/pnp/parport_probe.c @@ -76,7 +76,7 @@ static long read_polled(struct parport *port, char *buf, Byte |= (z<<4); if (temp) *(temp++) = Byte; - if (count++ == length) + if (++count == length) temp = NULL; /* Does the error line indicate end of data? */ if ((parport_read_status(port) & LP_PERRORP) == @@ -105,8 +105,8 @@ int parport_probe(struct parport *port, char *buffer, int len) switch (parport_ieee1284_nibble_mode_ok(port, 4)) { case 1: current->state=TASK_INTERRUPTIBLE; - schedule_timeout(1); /* HACK: wait 10ms because printer seems to - * ack wrong */ + /* HACK: wait 10ms because printer seems to ack wrong */ + schedule_timeout((HZ+99)/100); result = read_polled(port, buffer, len); break; case 0: diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c index ac1b53243c4a..d159506716ff 100644 --- a/drivers/sbus/char/pcikbd.c +++ b/drivers/sbus/char/pcikbd.c @@ -691,8 +691,7 @@ static int poll_aux_status(void) == AUX_STAT_OBF) pcimouse_inb(pcimouse_iobase + KBD_DATA_REG); current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + (5*HZ + 99) / 100; - schedule(); + schedule_timeout((5*HZ + 99)/100); retries++; } return (retries < MAX_RETRIES); diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c index 42a92f7b56ed..c4417ebe2d06 100644 --- a/drivers/sbus/char/sab82532.c +++ b/drivers/sbus/char/sab82532.c @@ -1629,8 +1629,7 @@ static void sab82532_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } @@ -1674,8 +1673,7 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout) while (info->xmit_cnt || !info->all_sent) { current->state = TASK_INTERRUPTIBLE; current->counter = 0; - current->timeout = jiffies + char_time; - schedule(); + schedule_timeout(char_time); if (signal_pending(current)) break; if (timeout && (orig_jiffies + timeout) < jiffies) diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c index 7cb48cb98761..a83d8b8ce349 100644 --- a/drivers/sbus/char/su.c +++ b/drivers/sbus/char/su.c @@ -1744,8 +1744,7 @@ su_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } @@ -1797,8 +1796,7 @@ su_wait_until_sent(struct tty_struct *tty, int timeout) #endif current->state = TASK_INTERRUPTIBLE; current->counter = 0; /* make us low-priority */ - current->timeout = jiffies + char_time; - schedule(); + schedule_timeout(char_time); if (signal_pending(current)) break; if (timeout && ((orig_jiffies + timeout) < jiffies)) diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c index 4676c338ef9c..750d89574122 100644 --- a/drivers/sbus/char/zs.c +++ b/drivers/sbus/char/zs.c @@ -1354,10 +1354,9 @@ static void send_break( struct sun_serial * info, int duration) if (!info->port) return; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; cli(); write_zsreg(info->zs_channel, 5, (info->curregs[5] | SND_BRK)); - schedule(); + schedule_timeout(duration); write_zsreg(info->zs_channel, 5, info->curregs[5]); sti(); } @@ -1543,8 +1542,7 @@ static void zs_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in index 1cc11f79ec60..34a0bbbb04c6 100644 --- a/drivers/scsi/Config.in +++ b/drivers/scsi/Config.in @@ -75,7 +75,7 @@ fi if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then - int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 + int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 4 int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20 bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 8e889f2ff452..4f7227875ec8 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -349,7 +349,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = { 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.2" +#define AIC7XXX_C_VERSION "5.1.3" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -3429,10 +3429,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel, * here so that we can delay all re-sent commands for this device for the * 4 seconds and then have our timer routine pick them back up. */ - if( timer_pending(&p->dev_timer[i]) ) - { - del_timer(&p->dev_timer[i]); - } + del_timer(&p->dev_timer[i]); p->dev_timer[i].expires = jiffies + (4 * HZ); add_timer(&p->dev_timer[i]); } @@ -3481,8 +3478,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel, "delayed_scbs queue!\n", p->host_no, channel, i, lun); scbq_init(&p->delayed_scbs[i]); } - if ( (p->delayed_scbs[i].head == NULL) && - timer_pending(&p->dev_timer[i]) ) + if ( p->delayed_scbs[i].head == NULL ) del_timer(&p->dev_timer[i]); } } @@ -4151,10 +4147,8 @@ aic7xxx_timer(struct aic7xxx_host *p) #endif for(i=0; idev_timer[i]) && - time_before_eq(p->dev_timer[i].expires, jiffies) ) + if ( del_timer(&p->dev_timer[i]) ) { - del_timer(&p->dev_timer[i]); p->dev_temp_queue_depth[i] = p->dev_max_queue_depth[i]; j = 0; while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) && @@ -9177,6 +9171,27 @@ aic7xxx_detect(Scsi_Host_Template *template) DSCOMMAND0); aic7xxx_load_seeprom(temp_p, &sxfrctl1); break; + case AHC_AIC7880: + /* + * Only set the DSCOMMAND0 register if this is a Rev B. + * chipset. For those, we also enable Ultra mode by + * force due to brain-damage on the part of some BIOSes + * We overload the devconfig variable here since we can. + */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) + pci_read_config_dword(pdev, DEVCONFIG, &devconfig); +#else + pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG, + &devconfig); +#endif + if ((devconfig & 0xff) >= 1) + { + aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) | + CACHETHEN | MPARCKEN) & ~DPARCKEN, + DSCOMMAND0); + } + aic7xxx_load_seeprom(temp_p, &sxfrctl1); + break; } diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c index 3b07e55d25f0..71b09c3de953 100644 --- a/drivers/sgi/char/sgiserial.c +++ b/drivers/sgi/char/sgiserial.c @@ -1279,10 +1279,9 @@ static void send_break( struct sgi_serial * info, int duration) if (!info->port) return; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; cli(); write_zsreg(info->zs_channel, 5, (info->curregs[5] | SND_BRK)); - schedule(); + schedule_timeout(duration); write_zsreg(info->zs_channel, 5, info->curregs[5]); sti(); } @@ -1483,8 +1482,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); + schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index 43bc92911a28..122b0198fb41 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -96,9 +96,7 @@ static unsigned char crystal_key[] = /* A 32 byte magic key sequence */ static void sleep(unsigned howlong) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + howlong; - schedule(); - current->timeout = 0; + schedule_timeout(howlong); } int probe_cs4232(struct address_info *hw_config) diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index da20e355f868..d0498b08ee0f 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -16,8 +16,8 @@ * 12k or so * Thomas Sailer : remove {in,out}_sleep_flag. It was used for the sleeper to * determine if it was woken up by the expiring timeout or by - * an explicit wake_up. current->timeout can be used instead; - * if 0, the wakeup was due to the timeout. + * an explicit wake_up. The return value from schedule_timeout + * can be used instead; if 0, the wakeup was due to the timeout. */ #include diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index b351c73db614..f74632927a14 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -816,8 +816,7 @@ static struct sound_queue sq; #define ONE_SECOND HZ /* in jiffies (100ths of a second) */ #define NO_TIME_LIMIT 0xffffffff #define SLEEP(queue, time_limit) \ - current->timeout = jiffies+(time_limit); \ - interruptible_sleep_on(&queue); + interruptible_sleep_on(&queue, (time_limit)); #define WAKE_UP(queue) (wake_up_interruptible(&queue)) /* diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 2a5f5b9d643f..f7dd0c8a399c 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -1017,11 +1017,8 @@ static int drain_dac1(struct es1370_state *s, int nonblock) } tmo = (count * HZ) / dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL]; tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; - current->timeout = jiffies + (tmo ? tmo : 1); - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1370: dma timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->dma_dac1.wait, &wait); current->state = TASK_RUNNING; @@ -1055,11 +1052,8 @@ static int drain_dac2(struct es1370_state *s, int nonblock) } tmo = (count * HZ) / DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV); tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; - current->timeout = jiffies + (tmo ? tmo : 1); - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1370: dma timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->dma_dac2.wait, &wait); current->state = TASK_RUNNING; @@ -2201,11 +2195,8 @@ static int es1370_midi_release(struct inode *inode, struct file *file) return -EBUSY; } tmo = (count * HZ) / 3100; - current->timeout = tmo ? jiffies + tmo : 0; - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1370: midi timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->midi.owait, &wait); current->state = TASK_RUNNING; diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 1c025fa2ea21..754aa443b3c9 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -1462,11 +1462,8 @@ static int drain_dac1(struct es1371_state *s, int nonblock) } tmo = (count * HZ) / s->dac1rate; tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; - current->timeout = jiffies + (tmo ? tmo : 1); - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1371: dma timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->dma_dac1.wait, &wait); current->state = TASK_RUNNING; @@ -1500,11 +1497,8 @@ static int drain_dac2(struct es1371_state *s, int nonblock) } tmo = (count * HZ) / s->dac2rate; tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; - current->timeout = jiffies + (tmo ? tmo : 1); - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1371: dma timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->dma_dac2.wait, &wait); current->state = TASK_RUNNING; @@ -2635,11 +2629,8 @@ static int es1371_midi_release(struct inode *inode, struct file *file) return -EBUSY; } tmo = (count * HZ) / 3100; - current->timeout = tmo ? jiffies + tmo : 0; - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "es1371: midi timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->midi.owait, &wait); current->state = TASK_RUNNING; diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index ed2b0019c822..4bf4cd38dd08 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -1927,11 +1927,8 @@ static int guswave_load_patch(int dev, int format, const char *addr, */ active_device = GUS_DEV_WAVE; - current->timeout = jiffies + HZ; - interruptible_sleep_on(&dram_sleeper); - if (!current->timeout) + if (!interruptible_sleep_on_timeout(&dram_sleeper, HZ)) printk("GUS: DMA Transfer timed out\n"); - current->timeout = 0; restore_flags(flags); } diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c index baf770a96643..d6b12e07b035 100644 --- a/drivers/sound/maui.c +++ b/drivers/sound/maui.c @@ -81,10 +81,8 @@ static int maui_wait(int mask) { if (inb(HOST_STAT_PORT) & mask) return 1; - current->timeout = jiffies + HZ / 10; current->state = TASK_INTERRUPTIBLE; - schedule(); - current->timeout = 0; + schedule_timeout(HZ / 10); if (signal_pending(current)) return 0; } diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c index 7b397b457758..8f0b6de86cfe 100644 --- a/drivers/sound/msnd_pinnacle.c +++ b/drivers/sound/msnd_pinnacle.c @@ -639,16 +639,12 @@ static void dsp_write_flush(void) if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags)) return; set_bit(F_WRITEFLUSH, &dev.flags); - current->timeout = jiffies + get_play_delay_jiffies(dev.DAPF.len) + HZ / 8; - interruptible_sleep_on(&dev.writeflush); + interruptible_sleep_on_timeout(&dev.writeflush, get_play_delay_jiffies(dev.DAPF.len) + HZ / 8); clear_bit(F_WRITEFLUSH, &dev.flags); if (!signal_pending(current)) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + get_play_delay_jiffies(DAP_BUFF_SIZE); - schedule(); - current->timeout = 0; - } else - current->timeout = 0; + schedule_timeout(get_play_delay_jiffies(DAP_BUFF_SIZE)); + } clear_bit(F_WRITING, &dev.flags); } @@ -923,12 +919,8 @@ static int dsp_read(char *buf, size_t len) if (count > 0) { set_bit(F_READBLOCK, &dev.flags); - current->timeout = jiffies + get_rec_delay_jiffies(DAR_BUFF_SIZE); - interruptible_sleep_on(&dev.readblock); - if (current->timeout == 0) + if (!interruptible_sleep_on_timeout(&dev.readblock, get_rec_delay_jiffies(DAR_BUFF_SIZE))) clear_bit(F_READING, &dev.flags); - else - current->timeout = 0; clear_bit(F_READBLOCK, &dev.flags); if (signal_pending(current)) return -EINTR; @@ -968,9 +960,7 @@ static int dsp_write(const char *buf, size_t len) if (count > 0) { set_bit(F_WRITEBLOCK, &dev.flags); - current->timeout = jiffies + get_play_delay_jiffies(DAP_BUFF_SIZE); - interruptible_sleep_on(&dev.writeblock); - current->timeout = 0; + interruptible_sleep_on_timeout(&dev.writeblock, get_play_delay_jiffies(DAP_BUFF_SIZE)); clear_bit(F_WRITEBLOCK, &dev.flags); if (signal_pending(current)) return -EINTR; @@ -1300,9 +1290,7 @@ __initfunc(static int calibrate_adc(WORD srate)) if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ / 3; - schedule(); - current->timeout = 0; + schedule_timeout(HZ / 3); printk("successful\n"); return 0; } diff --git a/drivers/sound/sgalaxy.c b/drivers/sound/sgalaxy.c index 9645a0b9bf04..e92aa8321b0a 100644 --- a/drivers/sound/sgalaxy.c +++ b/drivers/sound/sgalaxy.c @@ -29,9 +29,7 @@ static void sleep( unsigned howlong ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + howlong; - schedule(); - current->timeout = 0; + schedule(howlong); } #define DPORT 0x80 diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 82d0461a4bdb..b57cd186a7d9 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -1245,11 +1245,8 @@ static int drain_dac(struct sv_state *s, int nonblock) } tmo = (count * HZ) / s->ratedac; tmo >>= sample_shift[(s->fmt >> SV_CFMT_ASHIFT) & SV_CFMT_MASK]; - current->timeout = jiffies + (tmo ? tmo : 1); - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "sv: dma timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->dma_dac.wait, &wait); current->state = TASK_RUNNING; @@ -2025,11 +2022,8 @@ static int sv_midi_release(struct inode *inode, struct file *file) return -EBUSY; } tmo = (count * HZ) / 3100; - current->timeout = tmo ? jiffies + tmo : 0; - schedule(); - if (tmo && !current->timeout) + if (!schedule_timeout(tmo ? : 1) && tmo) printk(KERN_DEBUG "sv: midi timed out??\n"); - current->timeout = 0; } remove_wait_queue(&s->midi.owait, &wait); current->state = TASK_RUNNING; diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c index e1b092a7e031..3300795ea9dd 100644 --- a/drivers/sound/wavfront.c +++ b/drivers/sound/wavfront.c @@ -343,11 +343,8 @@ static int wavefront_sleep (wf_config *hw, int limit) { - current->timeout = jiffies + limit; current->state = TASK_INTERRUPTIBLE; - schedule(); - current->timeout = 0; - + schedule_timeout(limit); return signal_pending(current); } @@ -2266,8 +2263,7 @@ wavefront_should_cause_interrupt (wf_config *hw, int val, int port, int timeout) cli(); hw->irq_ok = 0; outb (val,port); - current->timeout = jiffies + timeout; - interruptible_sleep_on (&hw->interrupt_sleeper); + interruptible_sleep_on_timeout(&hw->interrupt_sleeper, timeout); restore_flags (flags); } diff --git a/fs/namei.c b/fs/namei.c index a5230c1a4e8f..974d92f17e70 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1196,7 +1196,7 @@ static inline int do_rename(const char * oldname, const char * newname) error = -ENOENT; if (!old_dentry->d_inode) - goto exit; + goto exit_old; { unsigned int flags = 0; diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index ea15ae968f78..cdcfc42209b2 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -94,7 +94,7 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size) poll_table wait_table; struct poll_table_entry entry; int init_timeout, max_timeout; - int timeout; + int timeout; long tmp_timeout; int retrans; int major_timeout_seen; int acknowledge_seen; @@ -173,6 +173,7 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size) wait_table.entry = &entry; current->state = TASK_INTERRUPTIBLE; if (!(file->f_op->poll(file, &wait_table) & POLLIN)) { + int timed_out; if (timeout > max_timeout) { /* JEJB/JSP 2/7/94 * This is useful to see if the system is @@ -182,17 +183,15 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size) } timeout = max_timeout; } - current->timeout = jiffies + timeout; - schedule(); + timed_out = !schedule_timeout(timeout); remove_wait_queue(entry.wait_address, &entry.wait); fput(file); current->state = TASK_RUNNING; if (signal_pending(current)) { - current->timeout = 0; result = -ERESTARTSYS; break; } - if (!current->timeout) { + if (timed_out) { if (n < retrans) continue; if (server->m.flags & NCP_MOUNT_SOFT) { @@ -208,8 +207,7 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size) } major_timeout_seen = 1; continue; - } else - current->timeout = 0; + } } else if (wait_table.nr) { remove_wait_queue(entry.wait_address, &entry.wait); fput(file); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2f63989140f3..d8a463befb66 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -555,8 +555,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, if (EX_WGATHER(exp) && (inode->i_writecount > 1 || (last_ino == inode->i_ino && last_dev == inode->i_dev))) { #if 0 - current->timeout = jiffies + 10 * HZ / 1000; - interruptible_sleep_on(&inode->i_wait); + interruptible_sleep_on_timeout(&inode->i_wait, 10 * HZ / 1000); #else dprintk("nfsd: write defer %d\n", current->pid); schedule_timeout((HZ+99)/100); diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt index c79c60fe8e0b..0f7ba34c1ce2 100644 --- a/fs/umsdos/README-WIP.txt +++ b/fs/umsdos/README-WIP.txt @@ -1,6 +1,6 @@ Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing (started by Peter T. Waltenberg ) -Final conversion to dentries Bill Hawes +(Final conversion to dentries Bill Hawes ) ---------- WARNING --------- WARNING --------- WARNING ----------- There is no warning any more. @@ -16,7 +16,7 @@ you are trying to use UMSDOS as root partition. Legend: those lines marked with '+' on the beggining of line indicates it passed all of my tests, and performed perfect in all of them. -Current status (980915) - UMSDOS dentry-Beta 0.83: +Current status (981018) - UMSDOS dentry-Beta 0.83: (1) pure MSDOS (no --linux-.--- EMD file): @@ -47,18 +47,18 @@ READ: + read file - works + switching MSDOS/UMSDOS - works + switching UMSDOS/MSDOS - works -- pseudo root things - DOES NOT WORK. COMMENTED OUT. See Notes below. +- pseudo root things - works mostly. See notes below. + resolve symlink - works + dereference symlink - works + dangling symlink - works -- hard links - DOES NOT WORK CORRECTLY ALWAYS. +- hard links - seems to work mostly + special files (block/char devices, FIFOs, sockets...) - works - various umsdos ioctls - works WRITE: -- create symlink - sometimes works, but see WARNING below -- create hardlink - works +- create symlink - works mostly, but see WARNING below +- create hardlink - works, but see portability WARNING below + create file - works + create special file - works + write to file - works @@ -88,7 +88,8 @@ Some current notes: Note: creating and using pseudo-hardlinks is always non-perfect, especially in filesystems that might be externally modified like umsdos. There is -example is specs file about it. +example is specs file about it. Specifically, moving directory which +contains hardlinks will break them. Warning: moving symlinks around may break them until umount/remount. @@ -97,17 +98,22 @@ I rm -rf directory: it is manifested as symlink apperantly being regular file instead of symlink until next umount/mount pair. Tracking this one down... -Wanted: I am currently looking for volunteers that already have UMSDOS -filesystems in pseudo-root, or are able to get them, to test PSEUDO-ROOT -stuff (and get new patches from me), which I currently can't do. Anyone know -of URL of nice UMSDOS pseudo-root ready image ? As always, any patches or -pointer to things done in wrong way (or ideas of better ways) are greatly -appreciated ! - -Note: If you are currently trying to use UMSDOS as root partition (with -linux installed in c:\linux) it will not work. Pseudo-root is currently -commented out. See 'wanted' above and contact me if you are interested in -testing it. +Note: (about pseudoroot) If you are currently trying to use UMSDOS as root +partition (with linux installed in c:\linux) it will boot, but there are +some problems. Volunteers ready to test pseudoroot are needed (preferably +ones with working backups or unimportant data). There are problems with +different interpretation of hard links in normal in pseudo-root modes, +resulting is 'silent delete' of them sometimes. Also, '/DOS' pseudo +directory is only partially re-implemented and buggy. It works most of the +time, though. + +Warning: (about creating hardlinks in pseudoroot mode) - hardlinks created in +pseudoroot mode are not compatibile with 'normal' hardlinks, and vice versa. +That is because harlink which is /foo in pseudoroot mode, becomes +/linux/foo in normal mode. I'm thinking about this one. However, since most +people either always use pseudoroot, or always use normal umsdos filesystem, +this is no showstopper. + ------------------------------------------------------------------------------ diff --git a/fs/umsdos/check.c b/fs/umsdos/check.c index a97f1cb91610..ab983212e2a8 100644 --- a/fs/umsdos/check.c +++ b/fs/umsdos/check.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -75,6 +76,7 @@ void check_sb (struct super_block *sb, const char c) /* * check an inode */ +extern struct inode_operations umsdos_rdir_inode_operations; void check_inode (struct inode *inode) { diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 24e39d47f2e8..1291163e9de7 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -44,7 +44,7 @@ static void umsdos_dentry_dput(struct dentry *dentry) } } -static struct dentry_operations umsdos_dentry_operations = +struct dentry_operations umsdos_dentry_operations = { umsdos_dentry_validate, /* d_validate(struct dentry *) */ NULL, /* d_hash */ @@ -123,7 +123,6 @@ static int umsdos_readdir_x (struct inode *dir, struct file *filp, if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root && !internal_read) { -Printk (("umsdos_readdir_x: what UMSDOS_SPECIAL_DIRFPOS /mn/?\n")); /* * We don't need to simulate this pseudo directory * when umsdos_readdir_x is called for internal operation @@ -134,6 +133,8 @@ Printk (("umsdos_readdir_x: what UMSDOS_SPECIAL_DIRFPOS /mn/?\n")); * linux root), it simulate a directory /DOS which points to * the real root of the file system. */ + + Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n")); if (filldir (dirbuf, "DOS", 3, UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO) == 0) { filp->f_pos++; @@ -477,6 +478,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name); * A lookup of DOS in the pseudo root will always succeed * and return the inode of the real root. */ + Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n")); inode = saved_root->d_inode; goto out_add; } @@ -542,7 +544,7 @@ dret->d_parent->d_name.name, dret->d_name.name); * which are recorded independently of the pseudo-root * mode. */ -printk(KERN_WARNING "umsdos_lookup_x: untested, inode == Pseudo_root\n"); +printk("umsdos_lookup_x: skipping DOS/linux\n"); ret = -ENOENT; goto out_dput; } @@ -557,7 +559,7 @@ out_add: ret = 0; out_dput: - if (dret != dentry) + if (dret && dret != dentry) d_drop(dret); dput(dret); out: diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 9e99f77d57f5..4b8e1bfcc68c 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -148,13 +148,13 @@ void umsdos_patch_dentry_inode(struct dentry *dentry, off_t f_pos) { struct inode *inode = dentry->d_inode; -Printk (("umsdos_patch_dentry_inode: inode=%lu\n", inode->i_ino)); +PRINTK (("umsdos_patch_dentry_inode: inode=%lu\n", inode->i_ino)); /* * Classify the inode based on EMD/non-EMD status. */ -Printk (("umsdos_patch_inode: call x_set_dirinfo(%p,%p,%lu)\n", -inode, dir, f_pos)); +PRINTK (("umsdos_patch_inode: call umsdos_set_dirinfo_new(%p,%lu)\n", +dentry, f_pos)); umsdos_set_dirinfo_new(dentry, f_pos); inode->u.umsdos_i.i_emd_dir = 0; @@ -275,8 +275,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name, ret); fill_new_filp (&filp, demd); filp.f_pos = inode->u.umsdos_i.pos; -Printk(("UMSDOS_notify_change: %s/%s reading at %u\n", -dentry->d_parent->d_name.name, dentry->d_name.name, filp.f_pos)); +Printk(("UMSDOS_notify_change: %s/%s reading at %d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, (int) filp.f_pos)); /* Read only the start of the entry since we don't touch the name */ ret = umsdos_emd_dir_read (&filp, (char *) &entry, UMSDOS_REC_SIZE); @@ -398,11 +398,14 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data, /* Check whether to change to the /linux root */ new_root = check_pseudo_root(sb); + if (new_root) { - pseudo_root = new_root->d_inode; /* sanity check */ if (new_root->d_op != &umsdos_dentry_operations) printk("umsdos_read_super: pseudo-root wrong ops!\n"); + + pseudo_root = new_root->d_inode; + saved_root = sb->s_root; sb->s_root = new_root; printk(KERN_INFO "UMSDOS: changed to alternate root\n"); @@ -411,6 +414,9 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data, /* if d_count is not 1, mount will fail with -EBUSY! */ if (sb->s_root->d_count > 1) { shrink_dcache_sb(sb); + if (sb->s_root->d_count > 1) { + printk(KERN_ERR "UMSDOS: root count %d > 1 !", sb->s_root->d_count); + } } return sb; diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 9f7be736df44..b0163041eee3 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -1033,12 +1033,12 @@ dentry->d_parent->d_name.name, dentry->d_name.name); if (empty == 1) { struct dentry *demd; -Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err)); demd = umsdos_get_emd_dentry(dentry); if (!IS_ERR(demd)) { err = -ENOENT; if (demd->d_inode) err = msdos_unlink (dentry->d_inode, demd); +Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err)); #ifdef UMSDOS_PARANOIA if (err) printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n", diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index 28a91de2d0bb..de0cfbeffdb6 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -107,8 +107,8 @@ printk (KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n"); * depending on whether this is an MS-DOS or * a UMSDOS directory */ -Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", -inode->i_ino)); +Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n", +dentry->d_parent->d_name.name, dentry->d_name.name)); umsdos_patch_dentry_inode(dentry, 0); /* N.B. Won't work -- /linux dentry will already have diff --git a/include/linux/if.h b/include/linux/if.h index 34c364bcf5a8..cd5f3139164e 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -43,7 +43,7 @@ #define IFF_PORTSEL 0x2000 /* can set media type */ #define IFF_AUTOMEDIA 0x4000 /* auto media select active */ -#define IFF_NODYNARP 0x8000 /* use static ARP only (HIPPI) */ +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ #ifdef __KERNEL__ /* diff --git a/include/linux/lp.h b/include/linux/lp.h index d258798db7dd..15656ff08ca3 100644 --- a/include/linux/lp.h +++ b/include/linux/lp.h @@ -25,7 +25,7 @@ #define LP_NOPA 0x0010 #define LP_ERR 0x0020 #define LP_ABORT 0x0040 -#if 0 +#ifdef LP_NEED_CAREFUL #define LP_CAREFUL 0x0080 #endif #define LP_ABORTOPEN 0x0100 @@ -41,10 +41,13 @@ #define LP_INIT_CHAR 1000 /* The parallel port specs apparently say that there needs to be - * a .5usec wait before and after the strobe. + * a .5usec wait before and after the strobe. Since there are wildly + * different computers running linux, I can't come up with a perfect + * value so if 20 is not good for you use `tunelp /dev/lp? -w ?`. + * You can also set it to 0 if your printer handle that. */ -#define LP_INIT_WAIT 1 +#define LP_INIT_WAIT 20 /* This is the amount of time that the driver waits for the printer to * catch up when the printer's buffer appears to be filled. If you @@ -128,7 +131,6 @@ struct lp_struct { unsigned int last_error; volatile unsigned int irq_detected:1; volatile unsigned int irq_missed:1; - unsigned int polled:1; }; /* @@ -174,7 +176,7 @@ struct lp_struct { */ #define LP_DELAY 50 -#define LP_POLLED(minor) (lp_table[(minor)].polled) +#define LP_POLLED(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE) #define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL) /* diff --git a/include/linux/mm.h b/include/linux/mm.h index 17fdc3533045..21967f6ee60c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -328,7 +328,6 @@ extern void put_cached_page(unsigned long); * Decide if we should try to do some swapout.. */ extern int free_memory_available(void); -extern struct task_struct * kswapd_task; /* vma is the first one with address < vma->vm_end, * and even address < vma->vm_start. Have to extend vma. */ diff --git a/include/linux/socket.h b/include/linux/socket.h index b83973f931f3..de7a1dbe3d12 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -250,6 +250,7 @@ struct ucred { /* TCP options - this way around because someone left a set in the c library includes */ #define TCP_NODELAY 1 #define TCP_MAXSEG 2 +#define TCP_CORK 3 /* Linux specific (for use with sendfile) */ #ifdef __KERNEL__ extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); diff --git a/include/net/tcp.h b/include/net/tcp.h index cb7fefc0823b..2ebee4e0df5d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -675,7 +675,7 @@ static __inline__ u32 tcp_receive_window(struct tcp_opt *tp) * scaling applied to the result. The caller does these things * if necessary. This is a "raw" window selection. */ -extern u32 __tcp_select_window(struct sock *sk, u32 cur_win); +extern u32 __tcp_select_window(struct sock *sk); /* Chose a new window to advertise, update state in tcp_opt for the * socket, and return result with RFC1323 scaling applied. The return @@ -686,13 +686,20 @@ extern __inline__ u16 tcp_select_window(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); u32 cur_win = tcp_receive_window(tp); - u32 new_win = __tcp_select_window(sk, cur_win); + u32 new_win = __tcp_select_window(sk); /* Never shrink the offered window */ - if(new_win < cur_win) + if(new_win < cur_win) { + /* Danger Will Robinson! + * Don't update rcv_wup/rcv_wnd here or else + * we will not be able to advertise a zero + * window in time. --DaveM + */ new_win = cur_win; - tp->rcv_wnd = new_win; - tp->rcv_wup = tp->rcv_nxt; + } else { + tp->rcv_wnd = new_win; + tp->rcv_wup = tp->rcv_nxt; + } /* RFC1323 scaling applied */ return new_win >> tp->rcv_wscale; @@ -706,7 +713,7 @@ extern __inline__ int tcp_raise_window(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); u32 cur_win = tcp_receive_window(tp); - u32 new_win = __tcp_select_window(sk, cur_win); + u32 new_win = __tcp_select_window(sk); return (new_win && (new_win > (cur_win << 1))); } @@ -790,8 +797,11 @@ static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb) * * Don't use the nagle rule for urgent data. */ - if (!sk->nonagle && skb->len < (tp->mss_cache >> 1) && tp->packets_out && - !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) + if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) || + (!sk->nonagle && + skb->len < (tp->mss_cache >> 1) && + tp->packets_out && + !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG))) nagle_check = 0; return (nagle_check && diff --git a/init/main.c b/init/main.c index dcefb24e8d93..df0873fde35e 100644 --- a/init/main.c +++ b/init/main.c @@ -1308,8 +1308,8 @@ static void __init do_basic_setup(void) */ extern struct inode *pseudo_root; if (pseudo_root != NULL){ - current->fs->root = pseudo_root; - current->fs->pwd = pseudo_root; + current->fs->root = pseudo_root->i_sb->s_root; + current->fs->pwd = pseudo_root->i_sb->s_root; } } #endif diff --git a/kernel/sched.c b/kernel/sched.c index 9f2caef8dfb7..08bc754ae351 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -750,7 +750,6 @@ static inline int __do_down(struct semaphore * sem, int task_state) schedule(); tsk->state = task_state; } - tsk->state = TASK_RUNNING; remove_wait_queue(&sem->wait, &wait); return ret; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index bb6a952fea0a..6ef166a146c5 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -38,7 +38,7 @@ /* External variables not in a header file. */ extern int panic_timeout; -extern int console_loglevel, C_A_D, swapout_interval; +extern int console_loglevel, C_A_D; extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern char binfmt_java_interpreter[], binfmt_java_appletviewer[]; extern int sysctl_overcommit_memory; @@ -199,8 +199,6 @@ static ctl_table kern_table[] = { static ctl_table vm_table[] = { {VM_SWAPCTL, "swapctl", &swap_control, sizeof(swap_control_t), 0644, NULL, &proc_dointvec}, - {VM_SWAPOUT, "swapout_interval", - &swapout_interval, sizeof(int), 0644, NULL, &proc_dointvec}, {VM_FREEPG, "freepages", &freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec}, {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL, diff --git a/mm/memory.c b/mm/memory.c index 9cfa87406667..22d90bfcfbdf 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -655,27 +655,28 @@ static int do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma, * Do we need to copy? */ if (is_page_shared(page_map)) { - if (new_page) { - if (PageReserved(mem_map + MAP_NR(old_page))) - ++vma->vm_mm->rss; - copy_cow_page(old_page,new_page); - flush_page_to_ram(old_page); - flush_page_to_ram(new_page); - flush_cache_page(vma, address); - set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); - free_page(old_page); - flush_tlb_page(vma, address); - return 1; - } + unlock_kernel(); + if (!new_page) + return 0; + + if (PageReserved(mem_map + MAP_NR(old_page))) + ++vma->vm_mm->rss; + copy_cow_page(old_page,new_page); + flush_page_to_ram(old_page); + flush_page_to_ram(new_page); flush_cache_page(vma, address); - set_pte(page_table, BAD_PAGE); - flush_tlb_page(vma, address); + set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); free_page(old_page); - oom(tsk); - return 0; + flush_tlb_page(vma, address); + return 1; } + if (PageSwapCache(page_map)) delete_from_swap_cache(page_map); + + /* We can release the kernel lock now.. */ + unlock_kernel(); + flush_cache_page(vma, address); set_pte(page_table, pte_mkdirty(pte_mkwrite(pte))); flush_tlb_page(vma, address); @@ -778,11 +779,14 @@ void vmtruncate(struct inode * inode, unsigned long offset) } +/* + * This is called with the kernel lock held, we need + * to return without it. + */ static int do_swap_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, pte_t * page_table, pte_t entry, int write_access) { - lock_kernel(); if (!vma->vm_ops || !vma->vm_ops->swapin) { swap_in(tsk, vma, page_table, pte_val(entry), write_access); flush_page_to_ram(pte_page(*page_table)); @@ -833,8 +837,8 @@ static int do_anonymous_page(struct task_struct * tsk, struct vm_area_struct * v * As this is called only for pages that do not currently exist, we * do not need to flush old virtual caches or the TLB. * - * This is called with the MM semaphore held, but without the kernel - * lock. + * This is called with the MM semaphore and the kernel lock held. + * We need to release the kernel lock as soon as possible.. */ static int do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, int write_access, pte_t *page_table) @@ -842,19 +846,19 @@ static int do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long page; pte_t entry; - if (!vma->vm_ops || !vma->vm_ops->nopage) + if (!vma->vm_ops || !vma->vm_ops->nopage) { + unlock_kernel(); return do_anonymous_page(tsk, vma, page_table, write_access); + } /* * The third argument is "no_share", which tells the low-level code * to copy, not share the page even if sharing is possible. It's * essentially an early COW detection. - * - * We need to grab the kernel lock for this.. */ - lock_kernel(); page = vma->vm_ops->nopage(vma, address & PAGE_MASK, (vma->vm_flags & VM_SHARED)?0:write_access); + unlock_kernel(); if (!page) return 0; @@ -896,7 +900,10 @@ static inline int handle_pte_fault(struct task_struct *tsk, struct vm_area_struct * vma, unsigned long address, int write_access, pte_t * pte) { - pte_t entry = *pte; + pte_t entry; + + lock_kernel(); + entry = *pte; if (!pte_present(entry)) { if (pte_none(entry)) @@ -907,16 +914,16 @@ static inline int handle_pte_fault(struct task_struct *tsk, entry = pte_mkyoung(entry); set_pte(pte, entry); flush_tlb_page(vma, address); - if (!write_access) - return 1; + if (write_access) { + if (!pte_write(entry)) + return do_wp_page(tsk, vma, address, pte); - if (pte_write(entry)) { entry = pte_mkdirty(entry); set_pte(pte, entry); flush_tlb_page(vma, address); - return 1; } - return do_wp_page(tsk, vma, address, pte); + unlock_kernel(); + return 1; } /* diff --git a/mm/slab.c b/mm/slab.c index 76ecab846a76..b7f0356e34f0 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -650,9 +650,9 @@ kmem_slab_destroy(kmem_cache_t *cachep, kmem_slab_t *slabp) } slabp->s_magic = SLAB_MAGIC_DESTROYED; - kmem_freepages(cachep, slabp->s_mem-slabp->s_offset); if (slabp->s_index) kmem_cache_free(cachep->c_index_cachep, slabp->s_index); + kmem_freepages(cachep, slabp->s_mem-slabp->s_offset); if (SLAB_OFF_SLAB(cachep->c_flags)) kmem_cache_free(cache_slabp, slabp); } diff --git a/mm/vmscan.c b/mm/vmscan.c index 6ceef56299c9..10b9918913bb 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -28,16 +28,10 @@ #include #include -/* - * How often do we do a pageout scan during normal conditions? - * Default is four times a second. - */ -int swapout_interval = HZ / 4; - /* * The wait queue for waking up the pageout daemon: */ -struct task_struct * kswapd_task = NULL; +static struct task_struct * kswapd_task = NULL; static void init_swap_timer(void); @@ -425,7 +419,7 @@ static int swap_out(unsigned int priority, int gfp_mask) * that we actually free'd up a page as a result. */ if (swap_out_process(pbest, gfp_mask) == 1) - return 1; + return 1; } out: return 0; diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index bcfe9e4de5e2..36062dfc0e19 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -383,9 +383,8 @@ static int atif_probe_device(struct atalk_iface *atif) /* * Defer 1/10th */ - current->timeout = jiffies + (HZ/10); current->state = TASK_INTERRUPTIBLE; - schedule(); + schedule_timeout(HZ/10); if(atif->status & ATIF_PROBE_FAIL) break; } diff --git a/net/core/dev.c b/net/core/dev.c index 768f2ada27f5..b4e8d140b653 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1375,7 +1375,7 @@ int dev_change_flags(struct device *dev, unsigned flags) */ dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP| - IFF_NODYNARP|IFF_SLAVE|IFF_MASTER| + IFF_SLAVE|IFF_MASTER|IFF_DYNAMIC| IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) | (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI)); diff --git a/net/core/sock.c b/net/core/sock.c index 1be5618e0458..caaaa21e62d1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.74 1998/10/21 05:40:38 davem Exp $ + * Version: $Id: sock.c,v 1.75 1998/11/07 10:54:38 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -969,8 +969,7 @@ void sock_def_wakeup(struct sock *sk) void sock_def_error_report(struct sock *sk) { - if (!sk->dead) - { + if (!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket,0); } @@ -978,8 +977,7 @@ void sock_def_error_report(struct sock *sk) void sock_def_readable(struct sock *sk, int len) { - if(!sk->dead) - { + if(!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket,1); } @@ -987,11 +985,14 @@ void sock_def_readable(struct sock *sk, int len) void sock_def_write_space(struct sock *sk) { - if(!sk->dead) - { + /* Do not wake up a writer until he can make "significant" + * progress. --DaveM + */ + if(!sk->dead && + ((atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf)) { wake_up_interruptible(sk->sleep); - /* Should agree with poll, otherwise some programs break */ + /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) sock_wake_async(sk->socket, 2); } diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 0e2733dcbb96..446ca1458d50 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -55,7 +55,7 @@ ctl_table core_table[] = { {NET_CORE_OPTMEM_MAX, "optmem_max", &sysctl_optmem_max, sizeof(int), 0644, NULL, &proc_dointvec}, -#endif +#endif /* CONFIG_NET */ { 0 } }; #endif diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 7c3a7362e768..780ed307f336 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1,6 +1,6 @@ /* linux/net/inet/arp.c * - * Version: $Id: arp.c,v 1.73 1998/10/21 05:36:02 davem Exp $ + * Version: $Id: arp.c,v 1.74 1998/11/01 22:15:06 davem Exp $ * * Copyright (C) 1994 by Florian La Roche * @@ -431,7 +431,7 @@ void arp_send(int type, int ptype, u32 dest_ip, * No arp on this interface. */ - if (dev->flags&(IFF_NOARP|IFF_NODYNARP)) + if (dev->flags&IFF_NOARP) return; /* @@ -547,7 +547,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) */ if (in_dev == NULL || arp->ar_hln != dev->addr_len || - dev->flags & (IFF_NOARP|IFF_NODYNARP) || + dev->flags & IFF_NOARP || skb->pkt_type == PACKET_OTHERHOST || skb->pkt_type == PACKET_LOOPBACK || arp->ar_pln != 4) diff --git a/net/ipv4/ip_masq.c b/net/ipv4/ip_masq.c index 4058cf3f7f5e..a05df9d2a156 100644 --- a/net/ipv4/ip_masq.c +++ b/net/ipv4/ip_masq.c @@ -4,7 +4,7 @@ * * Copyright (c) 1994 Pauline Middelink * - * $Id: ip_masq.c,v 1.26 1998/09/24 03:38:58 davem Exp $ + * $Id: ip_masq.c,v 1.27 1998/11/07 14:59:24 davem Exp $ * * * See ip_fw.c for original log @@ -1011,14 +1011,19 @@ int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr) switch (skb->ip_summed) { case CHECKSUM_NONE: + { + int datasz; doff = proto_doff(iph->protocol, h.raw); - csum = csum_partial(h.raw + doff, size - doff, 0); + datasz = size - doff; + if (datasz < 0) + return -1; + csum = csum_partial(h.raw + doff, datasz, 0); IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n", masq_proto_name(iph->protocol), csum); skb->csum = csum_partial(h.raw , doff, csum); - + } case CHECKSUM_HW: if (csum_tcpudp_magic(iph->saddr, iph->daddr, size, iph->protocol, skb->csum)) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 531227410f85..cfc606d761e9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.127 1998/10/04 07:04:32 davem Exp $ + * Version: $Id: tcp.c,v 1.130 1998/11/07 14:36:10 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -860,8 +860,8 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, int flags) if(copy > seglen) copy = seglen; + /* Determine how large of a buffer to allocate. */ tmp = MAX_HEADER + sk->prot->max_header; - queue_it = 0; if (copy < min(mss_now, tp->max_window >> 1) && !(flags & MSG_OOB)) { tmp += min(mss_now, tp->max_window); @@ -876,6 +876,7 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, int flags) queue_it = 1; } else { tmp += copy; + queue_it = 0; } skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL); @@ -1617,6 +1618,8 @@ struct sock *tcp_accept(struct sock *sk, int flags) req->class->destructor(req); tcp_openreq_free(req); sk->ack_backlog--; + if(sk->keepopen) + tcp_inc_slow_timer(TCP_SLT_KEEPALIVE); /* * This does not pass any already set errors on the new socket @@ -1655,48 +1658,86 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, return -EFAULT; switch(optname) { - case TCP_MAXSEG: -/* values greater than interface MTU won't take effect. however at - * the point when this call is done we typically don't yet know - * which interface is going to be used - */ - if(val<1||val>MAX_WINDOW) - return -EINVAL; - tp->user_mss=val; - return 0; - case TCP_NODELAY: - sk->nonagle=(val==0)?0:1; - return 0; - default: - return(-ENOPROTOOPT); + case TCP_MAXSEG: + /* values greater than interface MTU won't take effect. however at + * the point when this call is done we typically don't yet know + * which interface is going to be used + */ + if(val < 1 || val > MAX_WINDOW) + return -EINVAL; + tp->user_mss = val; + return 0; + + case TCP_NODELAY: + /* You cannot try to use this and TCP_CORK in + * tandem, so let the user know. + */ + if (sk->nonagle == 2) + return -EINVAL; + sk->nonagle = (val == 0) ? 0 : 1; + return 0; + + case TCP_CORK: + /* When set indicates to always queue non-full frames. + * Later the user clears this option and we transmit + * any pending partial frames in the queue. This is + * meant to be used alongside sendfile() to get properly + * filled frames when the user (for example) must write + * out headers with a write() call first and then use + * sendfile to send out the data parts. + * + * You cannot try to use TCP_NODELAY and this mechanism + * at the same time, so let the user know. + */ + if (sk->nonagle == 1) + return -EINVAL; + if (val != 0) { + sk->nonagle = 2; + } else { + sk->nonagle = 0; + + if (tp->send_head) { + lock_sock(sk); + if (tp->send_head && + tcp_snd_test (sk, tp->send_head)) + tcp_write_xmit(sk); + release_sock(sk); + } + } + return 0; + + default: + return -ENOPROTOOPT; }; } -int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, +int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - int val; - int len; + int val, len; if(level != SOL_TCP) return tp->af_specific->getsockopt(sk, level, optname, optval, optlen); - + if(get_user(len,optlen)) return -EFAULT; - - len = min(len,sizeof(int)); + + len = min(len, sizeof(int)); switch(optname) { - case TCP_MAXSEG: - val=tp->user_mss; - break; - case TCP_NODELAY: - val=sk->nonagle; - break; - default: - return(-ENOPROTOOPT); + case TCP_MAXSEG: + val = tp->user_mss; + break; + case TCP_NODELAY: + val = (sk->nonagle == 1); + break; + case TCP_CORK: + val = (sk->nonagle == 2); + break; + default: + return -ENOPROTOOPT; }; if(put_user(len, optlen)) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 12b17b5be264..cfa0f74b7670 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.133 1998/10/21 05:38:53 davem Exp $ + * Version: $Id: tcp_input.c,v 1.136 1998/11/07 14:36:18 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -567,14 +567,6 @@ static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup) /* This is Jacobson's slow start and congestion avoidance. * SIGCOMM '88, p. 328. - * - * FIXME: What happens when the congestion window gets larger - * than the maximum receiver window by some large factor - * Suppose the pipeline never looses packets for a long - * period of time, then traffic increases causing packet loss. - * The congestion window should be reduced, but what it should - * be reduced to is not clear, since 1/2 the old window may - * still be larger than the maximum sending rate we ever achieved. */ static void tcp_cong_avoid(struct tcp_opt *tp) { @@ -1525,7 +1517,7 @@ static __inline__ void __tcp_ack_snd_check(struct sock *sk) * - delay time <= 0.5 HZ * - we don't have a window update to send * - must send at least every 2 full sized packets - * - must send an ACK if we have any SACKs + * - must send an ACK if we have any out of order data * * With an extra heuristic to handle loss of packet * situations and also helping the sender leave slow @@ -1538,8 +1530,8 @@ static __inline__ void __tcp_ack_snd_check(struct sock *sk) tcp_raise_window(sk) || /* We entered "quick ACK" mode or... */ tcp_in_quickack_mode(tp) || - /* We have pending SACKs */ - (tp->sack_ok && tp->num_sacks)) { + /* We have out of order data */ + (skb_peek(&tp->out_of_order_queue) != NULL)) { /* Then ack it now */ tcp_send_ack(sk); } else { @@ -1655,8 +1647,11 @@ static int prune_queue(struct sock *sk) return 0; } - /* Now continue with the receive queue if it wasn't enough */ - while ((skb = skb_peek_tail(&sk->receive_queue))) { + /* Now continue with the receive queue if it wasn't enough. + * But only do this if we are really being abused. + */ + while ((atomic_read(&sk->rmem_alloc) >= (sk->rcvbuf * 2)) && + (skb = skb_peek_tail(&sk->receive_queue))) { /* Never toss anything when we've seen the FIN. * It's just too complex to recover from it. */ @@ -1679,8 +1674,6 @@ static int prune_queue(struct sock *sk) TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, tp->copied_seq); kfree_skb(skb); - if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) - break; } return 0; } @@ -1771,7 +1764,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, goto discard; } } else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una && - atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) { + atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) { /* Bulk data transfer: receiver */ __skb_pull(skb,th->doff*4); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 728bfdb5c365..75de39dec892 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.161 1998/10/03 09:38:05 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.162 1998/11/07 11:50:26 davem Exp $ * * IPv4 specific functions * @@ -1633,6 +1633,9 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len) /* Count it even if it's bad */ tcp_statistics.TcpInSegs++; + if (len < sizeof(struct tcphdr)) + goto bad_packet; + /* Try to use the device checksum if provided. */ switch (skb->ip_summed) { case CHECKSUM_NONE: @@ -1647,6 +1650,7 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len) ntohs(th->dest), len, skb->len, ntohs(skb->nh.iph->tot_len)); + bad_packet: tcp_statistics.TcpInErrs++; goto discard_it; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3e1ebfa4f201..596c72eeeeb7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.95 1998/09/27 12:57:13 freitag Exp $ + * Version: $Id: tcp_output.c,v 1.96 1998/11/07 10:54:40 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -390,7 +390,7 @@ void tcp_write_xmit(struct sock *sk) * * Note, we don't "adjust" for TIMESTAMP or SACK option bytes. */ -u32 __tcp_select_window(struct sock *sk, u32 cur_win) +u32 __tcp_select_window(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; unsigned int mss = tp->mss_cache; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 81799718af72..ea46d326893d 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.53 1998/09/15 02:11:39 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.55 1998/11/07 11:55:42 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -183,8 +183,8 @@ void tcp_probe_timer(unsigned long data) return; if (atomic_read(&sk->sock_readers)) { - /* Try again in second. */ - tcp_reset_xmit_timer(sk, TIME_PROBE0, HZ); + /* Try again later. */ + tcp_reset_xmit_timer(sk, TIME_PROBE0, HZ/5); return; } @@ -229,6 +229,9 @@ static __inline__ int tcp_keepopen_proc(struct sock *sk) sk->err = ETIMEDOUT; tcp_set_state(sk, TCP_CLOSE); + sk->shutdown = SHUTDOWN_MASK; + if (!sk->dead) + sk->state_change(sk); } else { tp->probes_out++; tp->pending = TIME_KEEPOPEN; @@ -433,8 +436,8 @@ void tcp_retransmit_timer(unsigned long data) } if (atomic_read(&sk->sock_readers)) { - /* Try again in a second. */ - tcp_reset_xmit_timer(sk, TIME_RETRANS, HZ); + /* Try again later */ + tcp_reset_xmit_timer(sk, TIME_RETRANS, HZ/20); return; } lock_sock(sk); @@ -463,10 +466,14 @@ void tcp_retransmit_timer(unsigned long data) tp->fackets_out = 0; tp->retrans_out = 0; if (tp->retransmits == 0) { - /* remember window where we lost + /* Remember window where we lost: * "one half of the current window but at least 2 segments" + * + * Here "current window" means the effective one, which + * means it must be an accurate representation of our current + * sending rate _and_ the snd_wnd. */ - tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2); + tp->snd_ssthresh = max(min(tp->snd_wnd, tp->snd_cwnd) >> 1, 2); tp->snd_cwnd_cnt = 0; tp->snd_cwnd = 1; } diff --git a/net/ipv4/timer.c b/net/ipv4/timer.c index 58a2169c765e..df3c9cce5801 100644 --- a/net/ipv4/timer.c +++ b/net/ipv4/timer.c @@ -5,7 +5,7 @@ * * TIMER - implementation of software timers for IP. * - * Version: $Id: timer.c,v 1.12 1998/08/28 01:15:29 davem Exp $ + * Version: $Id: timer.c,v 1.14 1998/11/07 11:55:43 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -74,7 +74,8 @@ void net_timer (unsigned long data) /* Only process if socket is not in use. */ if (atomic_read(&sk->sock_readers)) { - sk->timer.expires = jiffies+HZ; + /* Try again later. */ + sk->timer.expires = jiffies+HZ/20; add_timer(&sk->timer); return; } @@ -111,11 +112,10 @@ void net_timer (unsigned long data) case TIME_CLOSE: /* We've waited long enough, close the socket. */ - sk->state = TCP_CLOSE; - net_delete_timer (sk); + tcp_set_state(sk, TCP_CLOSE); + sk->shutdown = SHUTDOWN_MASK; if (!sk->dead) sk->state_change(sk); - sk->shutdown = SHUTDOWN_MASK; net_reset_timer (sk, TIME_DONE, TCP_DONE_TIME); break; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a1402936d00b..a95698db5a80 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.93 1998/10/03 09:38:50 davem Exp $ + * $Id: tcp_ipv6.c,v 1.94 1998/11/07 11:50:33 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -1331,6 +1331,9 @@ int tcp_v6_rcv(struct sk_buff *skb, unsigned long len) tcp_statistics.TcpInSegs++; + if (len < sizeof(struct tcphdr)) + goto bad_packet; + /* * Try to use the device checksum if provided. */ @@ -1341,6 +1344,7 @@ int tcp_v6_rcv(struct sk_buff *skb, unsigned long len) case CHECKSUM_HW: if (tcp_v6_check(th,len,saddr,daddr,skb->csum)) { printk(KERN_DEBUG "tcp csum failed\n"); + bad_packet: tcp_statistics.TcpInErrs++; goto discard_it; } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 23e94b5a5dae..a281c966bbee 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -427,7 +427,7 @@ void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, continue; if (failure) { - sk->err = -ENOBUFS; + sk->err = ENOBUFS; sk->state_change(sk); continue; } @@ -442,12 +442,12 @@ void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, } } if (skb2 == NULL) { - sk->err = -ENOBUFS; + sk->err = ENOBUFS; sk->state_change(sk); /* Clone failed. Notify ALL listeners. */ failure = 1; } else if (netlink_broadcast_deliver(sk, skb2)) { - sk->err = -ENOBUFS; + sk->err = ENOBUFS; sk->state_change(sk); } else skb2 = NULL; -- 2.39.5