From ec010c86e7282979991a69268b68fcab256200c7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:31 -0500 Subject: [PATCH] Import 1.1.19 --- Makefile | 2 +- drivers/char/keyboard.c | 2 +- drivers/char/pty.c | 63 +++++++++++++++++++++++++++----------- drivers/char/serial.c | 66 ++++++++++++++++++++++++++++++++++++---- drivers/net/ppp.c | 8 +++++ drivers/net/slip.c | 7 ++++- drivers/scsi/ChangeLog | 36 ++++++++++++++++++++++ drivers/scsi/aha1542.c | 6 ++-- drivers/scsi/aha1740.c | 3 +- drivers/scsi/buslogic.c | 2 +- drivers/scsi/hosts.c | 6 ++-- drivers/scsi/scsi.c | 21 ++++++++++--- drivers/scsi/scsi.h | 19 ++++++++---- drivers/scsi/sg.c | 6 +++- drivers/scsi/sg.h | 2 ++ drivers/scsi/ultrastor.c | 2 +- drivers/scsi/wd7000.c | 2 +- include/linux/serial.h | 1 + include/linux/termios.h | 1 + init/main.c | 4 +++ net/inet/skbuff.c | 1 + net/socket.c | 3 +- net/unix/sock.c | 11 ++++--- 23 files changed, 219 insertions(+), 55 deletions(-) diff --git a/Makefile b/Makefile index d5c87f4ecba1..b07bb0bdebd3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 18 +SUBLEVEL = 19 all: Version zImage diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 53832dd8cabe..9c8bd47a91c3 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -468,7 +468,7 @@ static void lastcons(void) static void send_intr(void) { - if (tty->termios && I_IGNBRK(tty)) + if (!tty || (tty->termios && I_IGNBRK(tty))) return; tty_insert_flip_char(tty, 0, TTY_BREAK); } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 679b70195866..1dab4ca4c5cb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -32,9 +33,19 @@ struct pty_struct { #define PTY_MAGIC 0x5001 -#define PTY_BUF_SIZE 1024 +#define PTY_BUF_SIZE PAGE_SIZE/2 -static unsigned char tmp_buf[PTY_BUF_SIZE]; +/* + * tmp_buf is used as a temporary buffer by pty_write. We need to + * lock it in case the memcpy_fromfs blocks while swapping in a page, + * and some other program tries to do a pty write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the PTY's, since it significantly saves memory if + * large numbers of PTY's are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; struct tty_driver pty_driver, pty_slave_driver; static int pty_refcount; @@ -78,24 +89,34 @@ static int pty_write(struct tty_struct * tty, int from_user, unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c, n; + int c=0, n, r; + char *temp_buffer; if (!to || tty->stopped) return 0; - count = MIN(count, to->ldisc.receive_room(to)); - if (from_user) { - for (c = count; c > 0; c -= n) { - n = MIN(c, PTY_BUF_SIZE); - memcpy_fromfs(tmp_buf, buf, n); - to->ldisc.receive_buf(to, tmp_buf, 0, n); - buf += n; + down(&tmp_buf_sem); + temp_buffer = tmp_buf + + ((tty->driver.subtype-1) * PTY_BUF_SIZE); + while (count > 0) { + n = MIN(count, PTY_BUF_SIZE); + memcpy_fromfs(temp_buffer, buf, n); + r = to->ldisc.receive_room(to); + if (r <= 0) + break; + n = MIN(n, r); + to->ldisc.receive_buf(to, temp_buffer, 0, n); + buf += n; c+= n; + count -= n; } - } else - to->ldisc.receive_buf(to, buf, 0, count); + up(&tmp_buf_sem); + } else { + c = MIN(count, to->ldisc.receive_room(to)); + to->ldisc.receive_buf(to, buf, 0, c); + } - return count; + return c; } static int pty_write_room(struct tty_struct *tty) @@ -146,7 +167,13 @@ int pty_open(struct tty_struct *tty, struct file * filp) return -ENODEV; pty = pty_state + line; tty->driver_data = pty; - + + if (!tmp_buf) { + tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + } + if (tty->driver.subtype == PTY_TYPE_SLAVE) clear_bit(TTY_SLAVE_CLOSED, &tty->link->flags); wake_up_interruptible(&pty->open_wait); @@ -199,12 +226,12 @@ long pty_init(long kmem_start) pty_slave_driver.termios_locked = ttyp_termios_locked; pty_slave_driver.other = &pty_driver; + tmp_buf = 0; + if (tty_register_driver(&pty_driver)) - panic("Couldn't register pty driver\n"); + panic("Couldn't register pty driver"); if (tty_register_driver(&pty_slave_driver)) - panic("Couldn't register pty slave driver\n"); + panic("Couldn't register pty slave driver"); return kmem_start; } - - diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 3bc33c252fdc..623b804a8afc 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -499,6 +499,10 @@ static void rs_interrupt(int irq) int pass_counter = 0; struct async_struct *end_mark = 0; +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info) return; @@ -512,6 +516,8 @@ static void rs_interrupt(int irq) } end_mark = 0; + info->last_active = jiffies; + status = serial_inp(info, UART_LSR); if (status & UART_LSR_DR) receive_chars(info, &status); @@ -543,6 +549,10 @@ static void rs_interrupt_single(int irq) int pass_counter = 0; struct async_struct * info; +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info || !info->tty) return; @@ -561,6 +571,7 @@ static void rs_interrupt_single(int irq) break; } } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); + info->last_active = jiffies; } #else /* CONFIG_SERIAL_NEW_ISR */ @@ -574,6 +585,11 @@ static void rs_interrupt(int irq) struct async_struct * info; int done = 1, pass_counter = 0; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info) return; @@ -625,6 +641,11 @@ static void rs_interrupt_single(int irq) int status; struct async_struct * info; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info || !info->tty) return; @@ -697,13 +718,39 @@ static void do_softint(void *private) */ static void rs_timer(void) { + static unsigned long last_strobe = 0; + struct async_struct *info; + unsigned int i; + + if ((jiffies - last_strobe) >= 60*HZ) { + for (i=1; i < 16; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + cli(); + if (info->next_port) { + do { + serial_out(info, UART_IER, 0); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + info = info->next_port; + } while (info); + rs_interrupt(i); + } else + rs_interrupt_single(i); + sti(); + } + } + last_strobe = jiffies; + timer_table[RS_TIMER].expires = jiffies + 60 * HZ; + timer_active |= 1 << RS_TIMER; + if (IRQ_ports[0]) { cli(); rs_interrupt(0); sti(); timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; - timer_active |= 1 << RS_TIMER; } } @@ -757,7 +804,7 @@ static void free_all_interrupts(int irq_lines) /* * This routine figures out the correct timeout for a particular IRQ. * It uses the smallest timeout of all of the serial ports in a - * particular interrupt chain. + * particular interrupt chain. Now only used for IRQ 0.... */ static void figure_IRQ_timeout(int irq) { @@ -908,10 +955,8 @@ static int startup(struct async_struct * info) /* * Set up serial timers... */ - if (info->irq == 0) { - timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0]; - timer_active |= 1 << RS_TIMER; - } + timer_table[RS_TIMER].expires = jiffies + 2; + timer_active |= 1 << RS_TIMER; /* * and set the speed of the serial port @@ -1633,6 +1678,15 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, rs_wild_int_mask = check_wild_interrupts(0); return 0; + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct async_struct)); + if (error) + return error; + memcpy_tofs((struct async_struct *) arg, + info, sizeof(struct async_struct)); + return 0; + default: return -ENOIOCTLCMD; } diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 83bae0407c42..1c508bbb6827 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -146,6 +146,7 @@ static int ppp_open(struct tty_struct *); static void ppp_close(struct tty_struct *); #ifdef NEW_TTY_DRIVERS +static int ppp_receive_room(struct tty_struct *tty); static void ppp_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count); static void ppp_write_wakeup(struct tty_struct *tty); @@ -239,6 +240,7 @@ ppp_init(struct device *dev) #ifdef NEW_TTY_DRIVERS ppp_ldisc.magic = TTY_LDISC_MAGIC; + ppp_ldisc.receive_room = ppp_receive_room; ppp_ldisc.receive_buf = ppp_receive_buf; ppp_ldisc.write_wakeup = ppp_write_wakeup; #else @@ -891,6 +893,12 @@ ppp_unesc(struct ppp *ppp, unsigned char *c, int n) } #else +static int ppp_receive_room(struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} + + static void ppp_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count) { diff --git a/drivers/net/slip.c b/drivers/net/slip.c index a7cda604d7b6..f5c812e211e4 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -656,6 +656,10 @@ sl_close(struct device *dev) return(0); } +static int slip_receive_room(struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} /* * Handle the 'receiver data ready' interrupt. @@ -680,7 +684,7 @@ static void slip_receive_buf(struct tty_struct *tty, unsigned char *cp, /* Read the characters out of the buffer */ while (count--) { - if (*fp++) { + if (fp && *fp++) { sl->flags |= SLF_ERROR; cp++; continue; @@ -1048,6 +1052,7 @@ slip_init(struct device *dev) unsigned int, unsigned long)) slip_ioctl; sl_ldisc.select = NULL; sl_ldisc.receive_buf = slip_receive_buf; + sl_ldisc.receive_room = slip_receive_room; sl_ldisc.write_wakeup = slip_write_wakeup; if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) printk("ERROR: %d\n", i); diff --git a/drivers/scsi/ChangeLog b/drivers/scsi/ChangeLog index e1fe60c0bf79..2b21a20a4b76 100644 --- a/drivers/scsi/ChangeLog +++ b/drivers/scsi/ChangeLog @@ -1,5 +1,41 @@ +Wed Jun 1 21:12:13 1994 Eric Youngdale (eric@esp22) + + * scsi.h: Add new return code for reset() function: + SCSI_RESET_PUNT. + + * scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for + now. + + * aha1542.c: If the command responsible for the reset is not + pending, return SCSI_RESET_PUNT. + + * aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return + SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE. + +Tue May 31 19:36:01 1994 Eric Youngdale (eric@esp22) + + * buslogic.c: Do not print out message about "must be Adaptec" + if we have detected a buslogic card. Print out a warning message + if we are configuring for >16Mb, since the 445S at board level + D or earlier does not work right. The "D" level board can be made + to work by flipping an undocumented switch, but this is too subtle. + + Changes based upon patches in Yggdrasil distribution. + + * sg.c, sg.h: Return sense data to user. + + * aha1542.c, aha1740.c, buslogic.c: Do not panic if + sense buffer is wrong size. + + * hosts.c: Test for ultrastor card before any of the others. + + * scsi.c: Allow boot-time option for max_scsi_luns=? so that + buggy firmware has an easy work-around. + Sun May 15 20:24:34 1994 Eric Youngdale (eric@esp22) + * Linux 1.1.15 released. + Post-codefreeze thaw... * buslogic.[c,h]: New driver from David Gentzel. diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index dd6102c659ec..3d860e4469ca 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -460,7 +460,6 @@ int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) #ifndef DEBUG if (bufflen != sizeof(SCpnt->sense_buffer)) { printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - panic("aha1542.c"); }; #endif SCpnt->result = 0; @@ -1058,7 +1057,10 @@ int aha1542_reset(Scsi_Cmnd * SCpnt) } #endif - return SCSI_RESET_PENDING; + /* No active command at this time, so this means that each time we got + some kind of response the last time through. Tell the mid-level code + to request sense information in order to decide what to do next. */ + return SCSI_RESET_PUNT; } #ifdef CONFIG_BLK_DEV_SD diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index 1d564dfda13a..1174258e9af2 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -251,7 +251,6 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) if (bufflen != sizeof(SCpnt->sense_buffer)) { printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - panic("aha1740.c"); } SCpnt->result = 0; done(SCpnt); @@ -487,7 +486,7 @@ int aha1740_abort(Scsi_Cmnd * SCpnt) int aha1740_reset(Scsi_Cmnd * SCpnt) { DEB(printk("aha1740_reset called\n")); - return SCSI_RESET_SNOOZE; + return SCSI_RESET_PUNT; } int aha1740_biosparam(int size, int dev, int* ip) diff --git a/drivers/scsi/buslogic.c b/drivers/scsi/buslogic.c index 2f80a3a335e2..0f6ff587207f 100644 --- a/drivers/scsi/buslogic.c +++ b/drivers/scsi/buslogic.c @@ -1178,7 +1178,7 @@ int buslogic_reset(Scsi_Cmnd *SCpnt) #if BUSLOGIC_DEBUG buslogic_printk("buslogic_reset\n"); #endif - return SCSI_RESET_SNOOZE; + return SCSI_RESET_PUNT; } int buslogic_biosparam(int size, int dev, int *ip) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index e6971381643c..a4600282f91e 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -110,6 +110,9 @@ static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hos Scsi_Host_Template scsi_hosts[] = { +#ifdef CONFIG_SCSI_ULTRASTOR + ULTRASTOR_14F, +#endif #ifdef CONFIG_SCSI_AHA152X AHA152X, #endif @@ -141,9 +144,6 @@ Scsi_Host_Template scsi_hosts[] = #ifdef CONFIG_SCSI_T128 TRANTOR_T128, #endif -#ifdef CONFIG_SCSI_ULTRASTOR - ULTRASTOR_14F, -#endif #ifdef CONFIG_SCSI_7000FASST WD7000, #endif diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index e2716b0e0b6d..724155152881 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -192,6 +192,20 @@ static void scan_scsis_done (Scsi_Cmnd * SCpnt) #endif SCpnt->request.dev = 0xfffe; } + +#ifdef NO_MULTI_LUN +static int max_scsi_luns = 1; +#else +static int max_scsi_luns = 8; +#endif + +void scsi_luns_setup(char *str, int *ints) { + if (ints[0] != 1) + printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n"); + else + max_scsi_luns = ints[1]; +} + /* * Detecting SCSI devices : * We scan all present host adapter's busses, from ID 0 to ID 6. @@ -223,11 +237,7 @@ static void scan_scsis (void) * We need the for so our continue, etc. work fine. */ -#ifdef NO_MULTI_LUN - for (lun = 0; lun < 1; ++lun) -#else - for (lun = 0; lun < 8; ++lun) -#endif + for (lun = 0; lun < max_scsi_luns; ++lun) { scsi_devices[NR_SCSI_DEVICES].host = shpnt; scsi_devices[NR_SCSI_DEVICES].id = dev; @@ -1491,6 +1501,7 @@ int scsi_reset (Scsi_Cmnd * SCpnt) return 0; case SCSI_RESET_PENDING: return 0; + case SCSI_RESET_PUNT: case SCSI_RESET_WAKEUP: SCpnt->internal_timeout &= ~IN_RESET; scsi_request_sense (SCpnt); diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 8631158aa747..b386f35270b5 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -351,27 +351,34 @@ struct scatterlist { /* We do not know how to reset the bus, or we do not want to. Bummer. Anyway, just wait a little more for the command in question, and hope that - it eventually finishes */ + it eventually finishes. If it never finishes, the SCSI device could + hang, so use this with caution. */ #define SCSI_RESET_SNOOZE 0 +/* We do not know how to reset the bus, or we do not want to. Bummer. + We have given up on this ever completing. The mid-level code will + request sense information to decide how to proceed from here. */ +#define SCSI_RESET_PUNT 1 + /* This means that we were able to reset the bus. We have restarted all of the commands that should be restarted, and we should be able to continue on normally from here. We do not expect any interrupts that will return - DID_RESET to any of the other commands in the host_queue. */ -#define SCSI_RESET_SUCCESS 1 + DID_RESET to any of the other commands in the host_queue, and the mid-level + code does not need to do anything special to keep the commands alive. */ +#define SCSI_RESET_SUCCESS 2 /* We called for an reset of this bus, and we should get an interrupt when this succeeds. Each command should get it's own status passed up to scsi_done, but this has not happened yet. */ -#define SCSI_RESET_PENDING 2 +#define SCSI_RESET_PENDING 3 /* We did a reset, but do not expect an interrupt to signal DID_RESET. This tells the upper level code to request the sense info, and this should keep the command alive. */ -#define SCSI_RESET_WAKEUP 3 +#define SCSI_RESET_WAKEUP 4 /* Something went wrong, and we do not know how to fix it. */ -#define SCSI_RESET_ERROR 4 +#define SCSI_RESET_ERROR 5 void * scsi_malloc(unsigned int); int scsi_free(void *, unsigned int); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b217a79aae7c..73eeb0249b50 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -173,7 +173,9 @@ static int sg_read(struct inode *inode,struct file *filp,char *buf,int count) buf+=sizeof(struct sg_header); if (count>device->header.pack_len) count=device->header.pack_len; - memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header)); + if (count > sizeof(struct sg_header)) { + memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header)); + } } else count=0; @@ -193,6 +195,7 @@ static void sg_command_done(Scsi_Cmnd * SCpnt) SCpnt->request.dev=-1; return; } + memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); if (SCpnt->sense_buffer[0]) { device->header.result=EIO; @@ -211,6 +214,7 @@ static int sg_write(struct inode *inode,struct file *filp,char *buf,int count) int bsize,size,amt,i; unsigned char cmnd[MAX_COMMAND_SIZE]; struct scsi_generic *device=&scsi_generics[dev]; + if ((i=verify_area(VERIFY_READ,buf,count))) return i; if (countsockaddr_len = sockaddr_len; /* now its legal */ return(0); -- 2.39.5