diff -u --recursive --new-file v2.0.14/linux/Makefile linux/Makefile --- v2.0.14/linux/Makefile Wed Aug 21 09:18:07 1996 +++ linux/Makefile Wed Aug 21 09:13:52 1996 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 14 +SUBLEVEL = 15 ARCH = i386 diff -u --recursive --new-file v2.0.14/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.0.14/linux/drivers/block/floppy.c Sat Aug 10 10:03:14 1996 +++ linux/drivers/block/floppy.c Thu Aug 22 18:47:27 1996 @@ -662,7 +662,7 @@ { int fdc=FDC(drive); #ifdef FLOPPY_SANITY_CHECK - if (jiffies < UDP->select_delay + UDRS->select_date) + if (jiffies - UDRS->select_date < UDP->select_delay) DPRINT("WARNING disk change called early\n"); if (!(FDCS->dor & (0x10 << UNIT(drive))) || (FDCS->dor & 3) != UNIT(drive) || @@ -966,7 +966,7 @@ return 1; } - if (jiffies < delay){ + if (jiffies - delay < 0){ del_timer(&fd_timer); fd_timer.function = function; fd_timer.expires = delay; @@ -1415,7 +1415,7 @@ * again just before spinup completion. Beware that * after scandrives, we must again wait for selection. */ - if (ready_date > jiffies + DP->select_delay){ + if (ready_date - jiffies > DP->select_delay){ ready_date -= DP->select_delay; function = (timeout_fn) floppy_start; } else @@ -1685,9 +1685,13 @@ } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2); } if (handler) { - /* expected interrupt */ - floppy_tq.routine = (void *)(void *) handler; - queue_task_irq(&floppy_tq, &tq_timer); + if(intr_count >= 2) { + /* expected interrupt */ + floppy_tq.routine = (void *)(void *) handler; + queue_task_irq(&floppy_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } else + handler(); } else FDCS->reset = 1; is_alive("normal interrupt end"); @@ -1925,7 +1929,8 @@ unsigned long flags; floppy_tq.routine = (void *)(void *) handler; - queue_task(&floppy_tq, &tq_timer); + queue_task(&floppy_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); INT_OFF; while(command_status < 2 && NO_SIGNAL){ is_alive("wait_til_done"); @@ -2733,7 +2738,8 @@ if (TESTF(FD_NEED_TWADDLE)) twaddle(); floppy_tq.routine = (void *)(void *) floppy_start; - queue_task(&floppy_tq, &tq_timer); + queue_task(&floppy_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); #ifdef DEBUGT debugt("queue fd request"); #endif @@ -2754,7 +2760,8 @@ static void process_fd_request(void) { cont = &rw_cont; - queue_task(&request_tq, &tq_timer); + queue_task(&request_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); } static void do_fd_request(void) @@ -3649,7 +3656,7 @@ if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) return 1; - if (UDRS->last_checked + UDP->checkfreq < jiffies){ + if (UDP->checkfreq < jiffies - UDRS->last_checked){ lock_fdc(drive,0); poll_drive(0,0); process_fd_request(); diff -u --recursive --new-file v2.0.14/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.0.14/linux/drivers/char/Makefile Mon Aug 5 10:13:51 1996 +++ linux/drivers/char/Makefile Thu Aug 22 18:45:56 1996 @@ -141,6 +141,16 @@ endif endif +ifeq ($(CONFIG_PCWATCHDOG),y) +M = y +L_OBJS += pcwd.o +else + ifeq ($(CONFIG_PCWATCHDOG),m) + M_OBJS += pcwd.o + MM = m + endif +endif + ifdef CONFIG_SUN_MOUSE M = y endif @@ -193,16 +203,6 @@ M_OBJS += scc.o endif endif - -ifeq ($(CONFIG_PCWATCHDOG),y) -M = y -L_OBJS += pcwd.o -else - ifeq ($(CONFIG_PCWATCHDOG),m) - M_OBJS += pcwd.o - MM = m - endif -endif ifeq ($(CONFIG_BAYCOM),y) L_OBJS += baycom.o diff -u --recursive --new-file v2.0.14/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.0.14/linux/drivers/char/console.c Wed Jul 24 10:49:53 1996 +++ linux/drivers/char/console.c Wed Aug 21 13:47:49 1996 @@ -482,7 +482,7 @@ */ static void gotoxy(int currcons, int new_x, int new_y) { - int max_y; + int min_y, max_y; if (new_x < 0) x = 0; @@ -492,21 +492,28 @@ else x = new_x; if (decom) { - new_y += top; + min_y = top; max_y = bottom; - } else + } else { + min_y = 0; max_y = video_num_lines; - if (new_y < 0) - y = 0; + } + if (new_y < min_y) + y = min_y; + else if (new_y >= max_y) + y = max_y - 1; else - if (new_y >= max_y) - y = max_y - 1; - else - y = new_y; + y = new_y; pos = origin + y*video_size_row + (x<<1); need_wrap = 0; } +/* for absolute user moves, when decom is set */ +static void gotoxay(int currcons, int new_x, int new_y) +{ + gotoxy(currcons, new_x, decom ? (top+new_y) : new_y); +} + /* * Hardware scrollback support */ @@ -1075,7 +1082,7 @@ break; case 6: /* Origin relative/absolute */ decom = on_off; - gotoxy(currcons,0,0); + gotoxay(currcons,0,0); break; case 7: /* Autowrap on/off */ decawm = on_off; @@ -1683,12 +1690,12 @@ continue; case 'd': if (par[0]) par[0]--; - gotoxy(currcons,x,par[0]); + gotoxay(currcons,x,par[0]); continue; case 'H': case 'f': if (par[0]) par[0]--; if (par[1]) par[1]--; - gotoxy(currcons,par[1],par[0]); + gotoxay(currcons,par[1],par[0]); continue; case 'J': csi_J(currcons,par[0]); @@ -1739,7 +1746,7 @@ par[1] <= video_num_lines) { top=par[0]-1; bottom=par[1]; - gotoxy(currcons,0,0); + gotoxay(currcons,0,0); } continue; case 's': diff -u --recursive --new-file v2.0.14/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.0.14/linux/drivers/char/mem.c Mon Aug 5 10:13:51 1996 +++ linux/drivers/char/mem.c Thu Aug 22 18:45:56 1996 @@ -29,6 +29,9 @@ #ifdef CONFIG_ISDN void isdn_init(void); #endif +#ifdef CONFIG_PCWATCHDOG +void pcwatchdog_init(void); +#endif static int read_ram(struct inode * inode, struct file * file, char * buf, int count) { @@ -392,6 +395,7 @@ #if defined (CONFIG_BUSMOUSE) || defined(CONFIG_UMISC) || \ defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \ defined (CONFIG_ATIXL_BUSMOUSE) || defined(CONFIG_SOFT_WATCHDOG) || \ + defined (CONFIG_PCWATCHDOG) || \ defined (CONFIG_APM) || defined (CONFIG_RTC) || defined (CONFIG_SUN_MOUSE) misc_init(); #endif @@ -400,9 +404,6 @@ #endif #if CONFIG_QIC02_TAPE qic02_tape_init(); -#endif -#ifdef CONFIG_PCWATCHDOG - pcwatchdog_init(); #endif #if CONFIG_ISDN isdn_init(); diff -u --recursive --new-file v2.0.14/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.0.14/linux/drivers/char/misc.c Fri Apr 26 10:30:50 1996 +++ linux/drivers/char/misc.c Thu Aug 22 18:45:56 1996 @@ -67,6 +67,7 @@ extern int atixl_busmouse_init(void); extern int sun_mouse_init(void); extern void watchdog_init(void); +extern void pcwatchdog_init(void); extern int rtc_init(void); #ifdef CONFIG_PROC_FS @@ -218,6 +219,9 @@ #ifdef CONFIG_SOFT_WATCHDOG watchdog_init(); #endif +#ifdef CONFIG_PCWATCHDOG + pcwatchdog_init(); +#endif #ifdef CONFIG_APM apm_bios_init(); #endif diff -u --recursive --new-file v2.0.14/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c --- v2.0.14/linux/drivers/char/pcwd.c Mon Aug 5 10:13:51 1996 +++ linux/drivers/char/pcwd.c Fri Aug 23 09:11:25 1996 @@ -13,6 +13,8 @@ * inclusion in Linux 2.0.x kernels, thanks to Alan Cox. * 960717 Removed read/seek routines, replaced with ioctl. Also, added * check_region command due to Alan's suggestion. + * 960821 Made changes to compile in newer 2.0.x kernels. Added + * "cold reboot sense" entry. */ #include @@ -35,7 +37,7 @@ #include -#define WD_VER "0.41 (07/17/96)" +#define WD_VER "0.50 (08/21/96)" #define WD_MINOR 130 /* Minor device number */ #define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ @@ -160,7 +162,11 @@ printk("pcwd: Previous reboot was caused by the card.\n"); if (card_status & WD_T110) - printk("pcwd: CPU overheat sense\n"); + printk("pcwd: CPU overheat sense.\n"); + + if ((!(card_status & WD_WDRST)) && + (!(card_status & WD_T110))) + printk("pcwd: Cold boot sense.\n"); } static int pcwd_return_data(void) @@ -190,7 +196,7 @@ return(1); } -static int pcwd_ioctl(struct tty_struct *tty, struct file *file, +static int pcwd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int i, cdat, rv; @@ -246,7 +252,7 @@ MOD_DEC_USE_COUNT; } -struct file_operations pcwd_fops = { +static struct file_operations pcwd_fops = { NULL, /* Seek */ NULL, /* Read */ pcwd_write, /* Write */ @@ -255,8 +261,7 @@ pcwd_ioctl, /* IOctl */ NULL, /* MMAP */ pcwd_open, /* Open */ - pcwd_close, /* Close */ - NULL + pcwd_close /* Close */ }; static struct miscdevice pcwd_miscdev = { @@ -295,12 +300,12 @@ current_readport = WD_CTLSTAT_PORT2; if (!pcwd_checkcard()) { - printk("pcwd: No card detected.\n"); + printk("pcwd: No card detected, or wrong port assigned.\n"); return(-EIO); } else - printk("pcwd: Port available at 0x370.\n"); + printk("pcwd: Watchdog Rev.A detected at port 0x370\n"); } else - printk("pcwd: Port available at 0x270.\n"); + printk("pcwd: Watchdog Rev.A detected at port 0x270\n"); pcwd_showprevstate(); @@ -308,7 +313,7 @@ printk("pcwd: Requesting region entry\n"); #endif - request_region(current_ctlport, WD_PORT_EXTENT, "PCWD (Berkshire)"); + request_region(current_ctlport, WD_PORT_EXTENT, "PCWD Rev.A (Berkshire)"); #ifdef DEBUG printk("pcwd: character device creation.\n"); @@ -329,3 +334,20 @@ #endif } #endif + +/* +** TODO: +** +** Both Revisions: +** o) Support for revision B of the Watchdog Card +** o) Implement the rest of the IOCTLs as discussed with Alan Cox +** o) Implement only card heartbeat reset via IOCTL, not via write +** o) Faster card detection routines +** o) /proc device creation +** +** Revision B functions: +** o) /dev/temp device creation for temperature device (possibly use +** the one from the WDT drivers?) +** o) Direct Motorola controller chip access via read/write routines +** o) Autoprobe IO Ports for autodetection (possibly by chip detect?) +*/ diff -u --recursive --new-file v2.0.14/linux/drivers/char/psaux.c linux/drivers/char/psaux.c --- v2.0.14/linux/drivers/char/psaux.c Tue Jul 23 06:48:28 1996 +++ linux/drivers/char/psaux.c Fri Aug 23 15:40:12 1996 @@ -25,6 +25,9 @@ * Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com * * Modularised 8-Sep-95 Philip Blundell + * + * Fixed keyboard lockups at open time + * 3-Jul-96, 22-Aug-96 Roman Hodek */ /* Uncomment the following line if your mouse needs initialization. */ @@ -35,6 +38,7 @@ #include #include +#include #include #include #include @@ -258,10 +262,14 @@ fasync_aux(inode, file, 0); if (--aux_count) return; + /* disable kbd bh to avoid mixing of cmd bytes */ + disable_bh(KEYBOARD_BH); aux_write_cmd(AUX_INTS_OFF); /* disable controller ints */ poll_aux_status(); outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */ poll_aux_status(); + /* reenable kbd bh */ + enable_bh(KEYBOARD_BH); free_irq(AUX_IRQ, NULL); MOD_DEC_USE_COUNT; } @@ -316,11 +324,16 @@ return -EBUSY; } MOD_INC_USE_COUNT; + /* disable kbd bh to avoid mixing of cmd bytes */ + disable_bh(KEYBOARD_BH); poll_aux_status(); outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */ aux_write_dev(AUX_ENABLE_DEV); /* enable aux device */ aux_write_cmd(AUX_INTS_ON); /* enable controller ints */ poll_aux_status(); + /* reenable kbd bh */ + enable_bh(KEYBOARD_BH); + aux_ready = 0; return 0; } @@ -377,18 +390,33 @@ static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count) { - int i = count; + int retval = 0; + + if (count > 0) { + int written = 0; - while (i--) { - if (!poll_aux_status()) - return -EIO; - outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); - if (!poll_aux_status()) - return -EIO; - outb_p(get_user(buffer++),AUX_OUTPUT_PORT); + /* disable kbd bh to avoid mixing of cmd bytes */ + disable_bh(KEYBOARD_BH); + + do { + if (!poll_aux_status()) + break; + outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); + if (!poll_aux_status()) + break; + outb_p(get_user(buffer++),AUX_OUTPUT_PORT); + written++; + } while (--count); + /* reenable kbd bh */ + enable_bh(KEYBOARD_BH); + retval = -EIO; + if (written) { + retval = written; + inode->i_mtime = CURRENT_TIME; + } } - inode->i_mtime = CURRENT_TIME; - return count; + + return retval; } diff -u --recursive --new-file v2.0.14/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c --- v2.0.14/linux/drivers/isdn/icn/icn.c Sat Jun 29 20:36:22 1996 +++ linux/drivers/isdn/icn/icn.c Wed Aug 21 16:31:12 1996 @@ -687,6 +687,7 @@ { int len = skb->len; unsigned long flags; + struct sk_buff *nskb; if (len > 4000) { printk(KERN_WARNING @@ -701,8 +702,14 @@ save_flags(flags); cli(); card->sndcount[channel] += len; - skb_queue_tail(&card->spqueue[channel], skb); + nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb) { + skb_queue_tail(&card->spqueue[channel], nskb); + dev_kfree_skb(skb, FREE_WRITE); + } restore_flags(flags); + if (!nskb) + return 0; } return len; } diff -u --recursive --new-file v2.0.14/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c --- v2.0.14/linux/drivers/net/ibmtr.c Mon May 6 12:26:08 1996 +++ linux/drivers/net/ibmtr.c Wed Aug 21 09:12:49 1996 @@ -50,6 +50,11 @@ - detecting PCMCIA Card Removal in interrupt handler. if ISRP is FF, then a PCMCIA card has been removed + Changes by Paul Norton (pnorton@cts.com) : + - restructured the READ.LOG logic to prevent the transmit SRB + from being rudely overwritten before the transmit cycle is + complete. (August 15 1996) + Warnings !!!!!!!!!!!!!! This driver is only partially sanitized for support of multiple adapters. It will almost definitely fail if more than one @@ -168,6 +173,7 @@ static int tok_close(struct device *dev); static int tok_send_packet(struct sk_buff *skb, struct device *dev); static struct enet_statistics * tok_get_stats(struct device *dev); +void tr_readlog(struct device *dev); static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter}; @@ -331,6 +337,7 @@ memset(ti, 0, sizeof(struct tok_info)); ti->mmio= t_mmio; + ti->readlog_pending = 0; dev->priv = ti; /* this seems like the logical use of the field ... let's try some empirical tests @@ -730,6 +737,7 @@ ti->current_skb=NULL; } dev->tbusy=0; + if (ti->readlog_pending) tr_readlog(dev); } } break; @@ -746,6 +754,7 @@ ti->current_skb=NULL; } dev->tbusy=0; + if (ti->readlog_pending) tr_readlog(dev); } } break; @@ -761,7 +770,7 @@ ti->current_skb=NULL; open_ret_code = readb(ti->init_srb +offsetof(struct srb_open_response, ret_code)); - open_error_code = readw(ti->init_srb +offsetof(struct srb_open_response, error_code)); + open_error_code = ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, error_code))); if (open_ret_code==7) { @@ -774,7 +783,7 @@ DPRINTK("retrying open to adjust to ring speed\n"); else if ((open_error_code==0x2d) && ti->auto_ringspeedsave) DPRINTK("No signal detected for Auto Speed Detection\n"); - else DPRINTK("Unrecoverable error: error code = %02X\n", + else DPRINTK("Unrecoverable error: error code = %04x\n", open_error_code); } else if (!open_ret_code) { @@ -887,10 +896,6 @@ case REC_DATA: case XMIT_UI_FRAME: case XMIT_DIR_FRAME: - if (readb(ti->asb+2)!=0xff) /* checks ret_code */ - DPRINTK("ASB error %02X in cmd %02X\n", - (int)readb(ti->asb+2), - (int)readb(ti->asb)); break; default: @@ -899,6 +904,9 @@ } /* ASB command check */ + if (readb(ti->asb+2)!=0xff) /* checks ret_code */ + DPRINTK("ASB error %02X in cmd %02X\n", + (int)readb(ti->asb+2),(int)readb(ti->asb)); writeb(~ASB_FREE_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); } /* ASB response */ @@ -938,14 +946,10 @@ DPRINTK("New ring status: %02X\n", ring_status); if (ring_status & LOG_OVERFLOW) { - - writeb(DIR_READ_LOG, ti->srb); - writeb(INT_ENABLE, - ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - writeb(CMD_IN_SRB, - ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - dev->tbusy=1; /* really srb busy... */ - + if (dev->tbusy) + ti->readlog_pending = 1; + else + tr_readlog(dev); } } break; @@ -1269,6 +1273,7 @@ dev_kfree_skb(ti->current_skb,FREE_WRITE); ti->current_skb=NULL; mark_bh(NET_BH); + if (ti->readlog_pending) tr_readlog(dev); } static void tr_rx(struct device *dev) @@ -1468,7 +1473,18 @@ } return 0; -} +} + +void tr_readlog(struct device *dev) { + struct tok_info *ti; + ti=(struct tok_info *) dev->priv; + + ti->readlog_pending = 0; + writeb(DIR_READ_LOG, ti->srb); + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + dev->tbusy=1; /* really srb busy... */ +} /* tok_get_stats(): Basically a scaffold routine which will return the address of the tr_statistics structure associated with @@ -1493,16 +1509,21 @@ 0, 0, 0, NULL, tok_probe }; static int io = 0xa20; +static char *device = NULL; int init_module(void) { + if (device) + strcpy(dev_ibmtr.name,device); + else if (!dev_ibmtr.name[0]) strcpy(dev_ibmtr.name,"tr0"); + if (io == 0) printk("ibmtr: You should not use auto-probing with insmod!\n"); dev_ibmtr.base_addr = io; dev_ibmtr.irq = 0; if (register_netdev(&dev_ibmtr) != 0) { - printk("ibmtr: register_netdev() returned non-zero.\n"); + printk("ibmtr: No adapters were found.\n"); return -EIO; } return 0; diff -u --recursive --new-file v2.0.14/linux/drivers/net/ibmtr.h linux/drivers/net/ibmtr.h --- v2.0.14/linux/drivers/net/ibmtr.h Fri Apr 12 09:49:38 1996 +++ linux/drivers/net/ibmtr.h Wed Aug 21 09:12:49 1996 @@ -206,6 +206,7 @@ struct tr_statistics tr_stats; unsigned char auto_ringspeedsave; open_state open_status; + unsigned char readlog_pending; }; /* token ring adapter commands */ diff -u --recursive --new-file v2.0.14/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.0.14/linux/drivers/net/lance.c Thu Jun 6 12:59:42 1996 +++ linux/drivers/net/lance.c Wed Aug 21 09:12:49 1996 @@ -30,9 +30,10 @@ to Donald Becker. I didn't receive any answer on all my letters to him. Who knows why... But may be you are more lucky? ;-) SAW + Fixed 7990 autoIRQ failure and reversed unneeded alignment. 8/20/96 djb */ -static const char *version = "lance.c:v1.08.02 Mar 17 1996 tsbogend@bigbug.franken.de\n"; +static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; #include #include @@ -314,7 +315,8 @@ #if defined(CONFIG_PCI) if (pcibios_present()) { int pci_index; - printk("lance.c: PCI bios is present, checking for devices...\n"); + if (lance_debug > 1) + printk("lance.c: PCI bios is present, checking for devices...\n"); for (pci_index = 0; pci_index < 8; pci_index++) { unsigned char pci_bus, pci_device_fn; unsigned int pci_ioaddr; @@ -449,16 +451,19 @@ } #endif /* Make certain the data structures used by the LANCE are aligned and DMAble. */ - lp = (struct lance_private *) LANCE_KMALLOC(sizeof(*lp)); + lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7, + GFP_DMA | GFP_KERNEL)+7) & ~7); if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); memset(lp, 0, sizeof(*lp)); dev->priv = lp; lp->name = chipname; - /* I'm not sure that buffs also must be aligned but it's safer to do it -- SAW */ - lp->rx_buffs = (unsigned long) LANCE_KMALLOC(PKT_BUF_SZ*RX_RING_SIZE); - lp->tx_bounce_buffs = NULL; + lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE, + GFP_DMA | GFP_KERNEL); if (lance_need_isa_bounce_buffers) - lp->tx_bounce_buffs = LANCE_KMALLOC(PKT_BUF_SZ*TX_RING_SIZE); + lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, + GFP_DMA | GFP_KERNEL); + else + lp->tx_bounce_buffs = NULL; lp->chip_version = lance_version; @@ -516,7 +521,7 @@ } if (dev->irq >= 2) printk(" assigned IRQ %d", dev->irq); - else { + else if (lance_version != 0) { /* 7990 boards need DMA detection first. */ /* To auto-IRQ we enable the initialization-done and DMA error interrupts. For ISA boards we get a DMA error, but VLB and PCI boards will work. */ @@ -525,7 +530,7 @@ /* Trigger an initialization just for the interrupt. */ outw(0x0041, ioaddr+LANCE_DATA); - dev->irq = autoirq_report(1); + dev->irq = autoirq_report(2); if (dev->irq) printk(", probed IRQ %d", dev->irq); else { @@ -581,6 +586,20 @@ printk("DMA detection failed.\n"); return; } + } + + if (lance_version == 0 && dev->irq == 0) { + /* We may auto-IRQ now that we have a DMA channel. */ + /* Trigger an initialization just for the interrupt. */ + autoirq_setup(0); + outw(0x0041, ioaddr+LANCE_DATA); + + dev->irq = autoirq_report(4); + if (dev->irq == 0) { + printk(" Failed to detect the 7990 IRQ line.\n"); + return; + } + printk(" Auto-IRQ detected IRQ%d.\n", dev->irq); } if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { diff -u --recursive --new-file v2.0.14/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.0.14/linux/fs/binfmt_elf.c Sat Aug 17 21:19:28 1996 +++ linux/fs/binfmt_elf.c Wed Aug 21 12:09:31 1996 @@ -179,6 +179,7 @@ struct elf_phdr *elf_phdata = NULL; struct elf_phdr *eppnt; unsigned long load_addr; + int load_addr_set = 0; int elf_exec_fileno; int retval; unsigned long last_bss, elf_bss; @@ -247,7 +248,7 @@ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; - if (interp_elf_ex->e_type == ET_EXEC || load_addr != 0) { + if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { elf_type |= MAP_FIXED; vaddr = eppnt->p_vaddr; } @@ -266,8 +267,10 @@ return ~0UL; } - if (!load_addr && interp_elf_ex->e_type == ET_DYN) + if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { load_addr = error; + load_addr_set = 1; + } /* * Find the end of the file mapping for this phdr, and keep @@ -365,6 +368,7 @@ struct exec interp_ex; struct inode *interpreter_inode; unsigned long load_addr; + int load_addr_set = 0; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter; int i; @@ -588,8 +592,10 @@ elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr); #endif - if (!load_addr) + if (!load_addr_set) { load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; + load_addr_set = 1; + } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; diff -u --recursive --new-file v2.0.14/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.0.14/linux/fs/proc/array.c Sat Aug 17 21:19:28 1996 +++ linux/fs/proc/array.c Wed Aug 21 09:12:49 1996 @@ -860,13 +860,16 @@ * f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH * + (index into the line) */ -#ifdef __alpha__ -#define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %s %lu\n" -#define MAPS_LINE_MAX 73 /* sum of 16 1 16 1 4 1 16 1 5 1 10 1 */ -#else -#define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %s %lu\n" -#define MAPS_LINE_MAX 49 /* sum of 8 1 8 1 4 1 8 1 5 1 10 1 */ -#endif +/* for systems with sizeof(void*) == 4: */ +#define MAPS_LINE_FORMAT4 "%08lx-%08lx %s %08lx %s %lu\n" +#define MAPS_LINE_MAX4 49 /* sum of 8 1 8 1 4 1 8 1 5 1 10 1 */ + +/* for systems with sizeof(void*) == 8: */ +#define MAPS_LINE_FORMAT8 "%016lx-%016lx %s %016lx %s %lu\n" +#define MAPS_LINE_MAX8 73 /* sum of 16 1 16 1 4 1 16 1 5 1 10 1 */ + +#define MAPS_LINE_MAX MAPS_LINE_MAX8 + static int read_maps (int pid, struct file * file, char * buf, int count) { @@ -918,7 +921,8 @@ ino = 0; } - len = sprintf(line, MAPS_LINE_FORMAT, + len = sprintf(line, + sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8, map->vm_start, map->vm_end, str, map->vm_offset, kdevname(dev), ino); diff -u --recursive --new-file v2.0.14/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.0.14/linux/include/asm-alpha/system.h Mon Aug 5 10:13:54 1996 +++ linux/include/asm-alpha/system.h Wed Aug 21 09:12:49 1996 @@ -38,11 +38,12 @@ * (assuming they are running OSF/1 PALcode, I guess). */ struct el_common { - unsigned int size; /* size in bytes of logout area */ - int sbz1 : 31; /* should be zero */ - char retry : 1; /* retry flag */ - unsigned int proc_offset; /* processor-specific offset */ - unsigned int sys_offset; /* system-specific offset */ + unsigned int size; /* size in bytes of logout area */ + int sbz1 : 31; /* should be zero */ + char retry : 1; /* retry flag */ + unsigned int proc_offset; /* processor-specific offset */ + unsigned int sys_offset; /* system-specific offset */ + unsigned long code; /* machine check code */ }; extern void wrent(void *, unsigned long); diff -u --recursive --new-file v2.0.14/linux/include/asm-i386/irq.h linux/include/asm-i386/irq.h --- v2.0.14/linux/include/asm-i386/irq.h Sun Mar 10 09:28:56 1996 +++ linux/include/asm-i386/irq.h Fri Aug 23 08:18:12 1996 @@ -81,7 +81,7 @@ * a bit - without them it seems that the harddisk driver won't work on * all hardware. Arghh. */ -#define ACK_FIRST(mask) \ +#define ACK_FIRST(mask,nr) \ "inb $0x21,%al\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ @@ -90,10 +90,10 @@ "outb %al,$0x21\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ + "1:\tmovb $0x60+"#nr",%al\n\t" \ "outb %al,$0x20\n\t" -#define ACK_SECOND(mask) \ +#define ACK_SECOND(mask,nr) \ "inb $0xA1,%al\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ @@ -102,11 +102,12 @@ "outb %al,$0xA1\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ + "1:\tmovb $0x60+"#nr",%al\n\t" \ "outb %al,$0xA0\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ - "1:\toutb %al,$0x20\n\t" + "1:\tmovb $0x62,%al\n\t" \ + "outb %al,$0x20\n\t" #define UNBLK_FIRST(mask) \ "inb $0x21,%al\n\t" \ @@ -207,7 +208,7 @@ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ ENTER_KERNEL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ "sti\n\t" \ "movl %esp,%ebx\n\t" \ @@ -224,7 +225,7 @@ SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ ENTER_KERNEL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ "pushl $" #nr "\n\t" \ "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ @@ -238,7 +239,7 @@ SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ ENTER_KERNEL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ LEAVE_KERNEL \ RESTORE_MOST); @@ -255,7 +256,7 @@ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ ENTER_KERNEL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ "movl %esp,%ebx\n\t" \ "pushl %ebx\n\t" \ @@ -283,7 +284,7 @@ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ ENTER_KERNEL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ "sti\n\t" \ "movl %esp,%ebx\n\t" \ @@ -301,7 +302,7 @@ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ SMP_PROF_IPI_CNT \ "pushl $" #nr "\n\t" \ "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ @@ -312,7 +313,7 @@ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ RESTORE_MOST); #define BUILD_RESCHEDIRQ(nr) \ @@ -345,7 +346,7 @@ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ "sti\n\t" \ "movl %esp,%ebx\n\t" \ @@ -360,7 +361,7 @@ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ "pushl $" #nr "\n\t" \ "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ @@ -372,7 +373,7 @@ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ SAVE_MOST \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ RESTORE_MOST); #define BUILD_TIMER_IRQ(chip,nr,mask) \ @@ -386,7 +387,7 @@ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ - ACK_##chip(mask) \ + ACK_##chip(mask,(nr&7)) \ "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ "movl %esp,%ebx\n\t" \ "pushl %ebx\n\t" \ diff -u --recursive --new-file v2.0.14/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.0.14/linux/include/linux/sched.h Thu Jul 25 20:26:46 1996 +++ linux/include/linux/sched.h Sat Aug 24 13:13:15 1996 @@ -398,70 +398,58 @@ * to keep them correct. Use only these two functions to add/remove * entries in the queues. */ +extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) +{ + struct wait_queue *head = *p; + struct wait_queue *next = wait; + + if (head) { + next = head->next; + p = &head->next; + } + *p = wait; + wait->next = next; +} + extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) { unsigned long flags; -#ifdef DEBUG - if (wait->next) { - __label__ here; - unsigned long pc; - pc = (unsigned long) &&here; - here: - printk("add_wait_queue (%08lx): wait->next = %08lx\n",pc,(unsigned long) wait->next); - } -#endif save_flags(flags); cli(); - if (!*p) { - wait->next = wait; - *p = wait; - } else { - wait->next = (*p)->next; - (*p)->next = wait; - } + __add_wait_queue(p, wait); restore_flags(flags); } -extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) +extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) { - unsigned long flags; - struct wait_queue * tmp; -#ifdef DEBUG - unsigned long ok = 0; -#endif + struct wait_queue * next = wait->next; - save_flags(flags); - cli(); - if ((*p == wait) && -#ifdef DEBUG - (ok = 1) && -#endif - ((*p = wait->next) == wait)) { + if (wait == next) { *p = NULL; } else { - tmp = wait; - while (tmp->next != wait) { - tmp = tmp->next; -#ifdef DEBUG - if (tmp == *p) - ok = 1; -#endif + struct wait_queue *head = *p; + if (head == wait) + *p = next; + for (;;) { + struct wait_queue *nextlist = head->next; + if (nextlist == wait) + break; + head = nextlist; } - tmp->next = wait->next; + head->next = next; } wait->next = NULL; +} + +extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) +{ + unsigned long flags; + + save_flags(flags); + cli(); + __remove_wait_queue(p, wait); restore_flags(flags); -#ifdef DEBUG - if (!ok) { - __label__ here; - ok = (unsigned long) &&here; - printk("removed wait_queue not on list.\n"); - printk("list = %08lx, queue = %08lx\n",(unsigned long) p, (unsigned long) wait); - here: - printk("eip = %08lx\n",ok); - } -#endif } extern inline void select_wait(struct wait_queue ** wait_address, select_table * p) diff -u --recursive --new-file v2.0.14/linux/kernel/sched.c linux/kernel/sched.c --- v2.0.14/linux/kernel/sched.c Wed Aug 21 09:18:10 1996 +++ linux/kernel/sched.c Sat Aug 24 10:45:10 1996 @@ -501,11 +501,13 @@ if (current == task[0]) panic("task[0] trying to sleep"); current->state = state; - add_wait_queue(p, &wait); save_flags(flags); + cli(); + __add_wait_queue(p, &wait); sti(); schedule(); - remove_wait_queue(p, &wait); + cli(); + __remove_wait_queue(p, &wait); restore_flags(flags); } diff -u --recursive --new-file v2.0.14/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.0.14/linux/net/ipv4/ip_fw.c Sat Jun 29 12:00:48 1996 +++ linux/net/ipv4/ip_fw.c Wed Aug 21 08:33:37 1996 @@ -117,7 +117,7 @@ * Implement IP packet firewall */ -#ifdef CONFIG_IP_FIREWALL_DEBUG +#ifdef DEBUG_IP_FIREWALL #define dprintf1(a) printk(a) #define dprintf2(a1,a2) printk(a1,a2) #define dprintf3(a1,a2,a3) printk(a1,a2,a3) @@ -134,7 +134,7 @@ (ntohl(a)>>8)&0xFF,\ (ntohl(a))&0xFF); -#ifdef CONFIG_IP_FIREWALL_DEBUG +#ifdef DEBUG_IP_FIREWALL #define dprint_ip(a) print_ip(a) #else #define dprint_ip(a) @@ -291,7 +291,7 @@ if (!offset) { src_port=ntohs(tcp->source); dst_port=ntohs(tcp->dest); - if(!tcp->ack) + if(!tcp->ack && !tcp->rst) /* We do NOT have ACK, value TRUE */ notcpack=1; if(!tcp->syn || !notcpack) @@ -321,7 +321,7 @@ prt=IP_FW_F_ALL; break; } -#ifdef CONFIG_IP_FIREWALL_DEBUG +#ifdef DEBUG_IP_FIREWALL dprint_ip(ip->saddr); if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) @@ -610,7 +610,7 @@ ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC ); if ( ftmp == NULL ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: malloc said no\n"); #endif return( ENOMEM ); @@ -652,7 +652,7 @@ ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC ); if ( ftmp == NULL ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: malloc said no\n"); #endif return( ENOMEM ); @@ -704,7 +704,7 @@ if ( ftmp == NULL ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: chain is empty\n"); #endif restore_flags(flags); @@ -773,7 +773,7 @@ if ( len != sizeof(struct ip_fw) ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: len=%d, want %d\n",len, sizeof(struct ip_fw)); #endif return(NULL); @@ -781,7 +781,7 @@ if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n", frwl->fw_flg); #endif @@ -790,7 +790,7 @@ #ifndef CONFIG_IP_TRANSPARENT_PROXY if (frwl->fw_flg & IP_FW_F_REDIR) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n"); #endif return(NULL); @@ -799,7 +799,7 @@ #ifndef CONFIG_IP_MASQUERADE if (frwl->fw_flg & IP_FW_F_MASQ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n"); #endif return(NULL); @@ -808,7 +808,7 @@ if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: src range set but fw_nsp=%d\n", frwl->fw_nsp); #endif @@ -817,7 +817,7 @@ if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: dst range set but fw_ndp=%d\n", frwl->fw_ndp); #endif @@ -826,7 +826,7 @@ if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: too many ports (%d+%d)\n", frwl->fw_nsp,frwl->fw_ndp); #endif @@ -873,13 +873,13 @@ /* * Should be panic but... (Why ??? - AC) */ -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_acct_ctl: unknown request %d\n",stage); #endif return(EINVAL); } } -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_acct_ctl: unknown request %d\n",stage); #endif return(EINVAL); @@ -922,7 +922,7 @@ if ( len != sizeof(struct ip_fwpkt) ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: length=%d, expected %d\n", len, sizeof(struct ip_fwpkt)); #endif @@ -933,18 +933,18 @@ ip = &(ipfwp->fwp_iph); if ( !(viadev = dev_get(ipfwp->fwp_vianame)) ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame); #endif return(EINVAL); } else if ( viadev->pa_addr != ipfwp->fwp_via.s_addr ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: device \"%s\" has another IP address\n", ipfwp->fwp_vianame); #endif return(EINVAL); } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl, sizeof(struct iphdr)/sizeof(int)); #endif @@ -974,7 +974,7 @@ if ( len != sizeof(struct ip_fw_masq) ) { -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl (masq): length %d, expected %d\n", len, sizeof(struct ip_fw_masq)); @@ -1032,14 +1032,14 @@ /* * Should be panic but... (Why are BSD people panic obsessed ??) */ -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: unknown request %d\n",stage); #endif return(EINVAL); } } -#ifdef DEBUG_CONFIG_IP_FIREWALL +#ifdef DEBUG_IP_FIREWALL printk("ip_fw_ctl: unknown request %d\n",stage); #endif return(EINVAL); diff -u --recursive --new-file v2.0.14/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.0.14/linux/net/ipv4/tcp.c Mon Aug 5 10:13:55 1996 +++ linux/net/ipv4/tcp.c Sat Aug 24 10:38:57 1996 @@ -867,15 +867,24 @@ static void wait_for_tcp_memory(struct sock * sk) { release_sock(sk); - cli(); - if (!tcp_memory_free(sk) && - (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT) - && sk->err == 0 /* && check shutdown ?? */) - { + if (!tcp_memory_free(sk)) { + struct wait_queue wait = { current, NULL }; + sk->socket->flags &= ~SO_NOSPACE; - interruptible_sleep_on(sk->sleep); + add_wait_queue(sk->sleep, &wait); + for (;;) { + current->state = TASK_INTERRUPTIBLE; + if (tcp_memory_free(sk)) + break; + if (sk->shutdown & SEND_SHUTDOWN) + break; + if (sk->err) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(sk->sleep, &wait); } - sti(); lock_sock(sk); }