## Automatically generated incremental diff
## From:   linux-2.4.22-bk12
## To:     linux-2.4.22-bk13
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.22-bk12/Makefile linux-2.4.22-bk13/Makefile
--- linux-2.4.22-bk12/Makefile	2003-09-09 03:08:07.000000000 -0700
+++ linux-2.4.22-bk13/Makefile	2003-09-09 03:08:21.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 22
-EXTRAVERSION = -bk12
+EXTRAVERSION = -bk13
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.22-bk12/drivers/usb/acm.c linux-2.4.22-bk13/drivers/usb/acm.c
--- linux-2.4.22-bk12/drivers/usb/acm.c	2003-09-09 03:08:15.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/acm.c	2003-09-09 03:08:27.000000000 -0700
@@ -363,9 +363,10 @@
 
 	count = (count > acm->writesize) ? acm->writesize : count;
 
-	if (from_user)
-		copy_from_user(acm->writeurb.transfer_buffer, buf, count);
-	else
+	if (from_user) {
+		if (copy_from_user(acm->writeurb.transfer_buffer, buf, count))
+			return -EFAULT;
+	} else
 		memcpy(acm->writeurb.transfer_buffer, buf, count);
 
 	acm->writeurb.transfer_buffer_length = count;
diff -urN linux-2.4.22-bk12/drivers/usb/aiptek.c linux-2.4.22-bk13/drivers/usb/aiptek.c
--- linux-2.4.22-bk12/drivers/usb/aiptek.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/aiptek.c	2003-09-09 03:08:27.000000000 -0700
@@ -1102,7 +1102,8 @@
 	int num;
 
 	num = (count < 64) ? count : 64;
-	copy_from_user(buf, buffer, num);
+	if (copy_from_user(buf, buffer, num))
+		return -EFAULT;
 	buf[num] = '\0';
 
 	scan = buf;
diff -urN linux-2.4.22-bk12/drivers/usb/host/uhci-debug.h linux-2.4.22-bk13/drivers/usb/host/uhci-debug.h
--- linux-2.4.22-bk12/drivers/usb/host/uhci-debug.h	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/host/uhci-debug.h	2003-09-09 03:08:28.000000000 -0700
@@ -545,7 +545,8 @@
 	if (!access_ok(VERIFY_WRITE, buf, nbytes))
 		return -EINVAL;
 
-	copy_to_user(buf, up->data + pos, nbytes);
+	if (copy_to_user(buf, up->data + pos, nbytes))
+		return -EFAULT;
 
 	*ppos += nbytes;
 
diff -urN linux-2.4.22-bk12/drivers/usb/mdc800.c linux-2.4.22-bk13/drivers/usb/mdc800.c
--- linux-2.4.22-bk12/drivers/usb/mdc800.c	2003-06-13 07:51:36.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/mdc800.c	2003-09-09 03:08:28.000000000 -0700
@@ -726,7 +726,8 @@
 		else
 		{
 			/* memcpy Bytes */
-			copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts);
+			if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts))
+				return -EFAULT;
 			ptr+=sts;
 			left-=sts;
 			mdc800->out_ptr+=sts;
diff -urN linux-2.4.22-bk12/drivers/usb/serial/pl2303.c linux-2.4.22-bk13/drivers/usb/serial/pl2303.c
--- linux-2.4.22-bk12/drivers/usb/serial/pl2303.c	2003-09-09 03:08:17.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/serial/pl2303.c	2003-09-09 03:08:29.000000000 -0700
@@ -153,7 +153,8 @@
 	.shutdown =		pl2303_shutdown,
 };
 
-struct pl2303_private { 
+struct pl2303_private {
+	spinlock_t lock;
 	u8 line_control;
 	u8 line_status;
 	u8 termios_initialized;
@@ -170,7 +171,8 @@
 		if (!priv)
 			return -ENOMEM;
 		memset (priv, 0x00, sizeof (struct pl2303_private));
-		serial->port[i].private = priv;
+		spin_lock_init(&priv->lock);
+		usb_set_serial_port_data(&serial->port[i], priv);
 	}
 	return 0;
 }
@@ -223,25 +225,30 @@
 static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
-	struct pl2303_private *priv;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	unsigned int cflag;
 	unsigned char *buf;
 	int baud;
 	int i;
+	u8 control;
 
 	dbg("%s -  port %d, initialized = %d", __FUNCTION__, port->number, 
-	     ((struct pl2303_private *) port->private)->termios_initialized);
+	     priv->termios_initialized);
 
 	if ((!port->tty) || (!port->tty->termios)) {
 		dbg("%s - no tty structures", __FUNCTION__);
 		return;
 	}
 
-	if (!(((struct pl2303_private *) port->private)->termios_initialized)) {
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->termios_initialized) {
 		*(port->tty->termios) = tty_std_termios;
 		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-		((struct pl2303_private *) port->private)->termios_initialized = 1;
+		priv->termios_initialized = 1;
 	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	cflag = port->tty->termios->c_cflag;
 	/* check that they really want us to change something */
 	if (old_termios) {
@@ -341,13 +348,19 @@
 			     0, 0, buf, 7, 100);
 	dbg ("0x21:0x20:0:0  %d", i);
 
-	if (cflag && CBAUD) {
-		priv = port->private;
-		if ((cflag && CBAUD) == B0)
-			priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-		else
-			priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
-		set_control_lines (serial->dev, priv->line_control);
+	/* change control lines if we are switching to or from B0 */
+	spin_lock_irqsave(&priv->lock, flags);
+	control = priv->line_control;
+	if ((cflag & CBAUD) == B0)
+		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+	else
+		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+	if (control != priv->line_control) {
+		control = priv->line_control;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		set_control_lines(serial->dev, control);
+	} else {
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 	
 	buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
@@ -381,6 +394,9 @@
 		
 	dbg("%s -  port %d", __FUNCTION__, port->number);
 
+	usb_clear_halt(serial->dev, port->write_urb->pipe);
+	usb_clear_halt(serial->dev, port->read_urb->pipe);
+
 #define FISH(a,b,c,d)								\
 	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
 			       b, a, c, d, buf, 1, 100);			\
@@ -432,6 +448,7 @@
 {
 	struct usb_serial *serial;
 	struct pl2303_private *priv;
+	unsigned long flags;
 	unsigned int c_cflag;
 	int result;
 
@@ -448,10 +465,11 @@
 			c_cflag = port->tty->termios->c_cflag;
 			if (c_cflag & HUPCL) {
 				/* drop DTR and RTS */
-				priv = port->private;
+				priv = usb_get_serial_port_data(port);
+				spin_lock_irqsave(&priv->lock, flags);
 				priv->line_control = 0;
-				set_control_lines (port->serial->dev,
-						   priv->line_control);
+				spin_unlock_irqrestore (&priv->lock, flags);
+				set_control_lines (port->serial->dev, 0);
 			}
 		}
 
@@ -479,12 +497,15 @@
 
 static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
 {
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	unsigned int arg;
+	u8 control;
 
 	if (copy_from_user(&arg, value, sizeof(int)))
 		return -EFAULT;
 
+	spin_lock_irqsave (&priv->lock, flags);
 	switch (cmd) {
 		case TIOCMBIS:
 			if (arg & TIOCM_RTS)
@@ -508,17 +529,25 @@
 			priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
 			break;
 	}
+	control = priv->line_control;
+	spin_unlock_irqrestore (&priv->lock, flags);
 
-	return set_control_lines (port->serial->dev, priv->line_control);
+	return set_control_lines (port->serial->dev, control);
 }
 
 static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
 {
-	struct pl2303_private *priv = port->private;
-	unsigned int mcr = priv->line_control;
-	unsigned int status = priv->line_status;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int mcr;
+	unsigned int status;
 	unsigned int result;
 
+	spin_lock_irqsave (&priv->lock, flags);
+	mcr = priv->line_control;
+	status = priv->line_status;
+	spin_unlock_irqrestore (&priv->lock, flags);
+
 	result = ((mcr & CONTROL_DTR)		? TIOCM_DTR : 0)
 		  | ((mcr & CONTROL_RTS)	? TIOCM_RTS : 0)
 		  | ((status & UART_CTS)	? TIOCM_CTS : 0)
@@ -557,7 +586,6 @@
 	return -ENOIOCTLCMD;
 }
 
-
 static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
 {
 	struct usb_serial *serial = port->serial;
@@ -586,8 +614,10 @@
 
 	dbg("%s", __FUNCTION__);
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree (serial->port[i].private);
+	for (i = 0; i < serial->num_ports; ++i) {
+		kfree (usb_get_serial_port_data(&serial->port[i]));
+		usb_set_serial_port_data(&serial->port[i], NULL);
+	}		
 }
 
 
@@ -595,17 +625,30 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
+
+	dbg("%s (%d)", __FUNCTION__, port->number);
 
 	/* ints auto restart... */
 
-	if (!serial) {
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
-	if (urb->status) {
-		urb->status = 0;
+	if (!serial) {
 		return;
 	}
 
@@ -615,7 +658,9 @@
 		return;
 
 	/* Save off the uart status for others to look at */
+	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_status = data[UART_STATE];
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return;
 }
@@ -625,9 +670,10 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
 	int i;
 	int result;
 	u8 status;
@@ -667,7 +713,10 @@
 
 	/* get tty_flag from status */
 	tty_flag = TTY_NORMAL;
+
+	spin_lock_irqsave(&priv->lock, flags);
 	status = priv->line_status;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
@@ -742,9 +791,14 @@
 
 static int __init pl2303_init (void)
 {
-	usb_serial_register (&pl2303_device);
+	int retval;
+	retval = usb_serial_register(&pl2303_device);
+	if (retval)
+		goto failed_usb_serial_register;
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
+failed_usb_serial_register:
+	return retval;
 }
 
 
diff -urN linux-2.4.22-bk12/drivers/usb/serial/usb-serial.h linux-2.4.22-bk13/drivers/usb/serial/usb-serial.h
--- linux-2.4.22-bk12/drivers/usb/serial/usb-serial.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-bk13/drivers/usb/serial/usb-serial.h	2003-09-09 03:08:29.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- *	Copyright (C) 1999 - 2002
+ *	Copyright (C) 1999 - 2003
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -67,7 +67,7 @@
  * usb_serial_port: structure for the specific ports of a device.
  * @magic: magic number for internal validity of this pointer.
  * @serial: pointer back to the struct usb_serial owner of this port.
- * @tty: pointer to the coresponding tty for this port.
+ * @tty: pointer to the corresponding tty for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
  * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -118,6 +118,16 @@
 	struct semaphore	sem;
 	void *			private;
 };
+/* get and set the port private data pointer helper functions */
+static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+{
+	return port->private;
+}
+
+static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+{
+	port->private = data;
+}
 
 /**
  * usb_serial - structure used by the usb-serial core for a device
@@ -156,6 +166,16 @@
 
 #define NUM_DONT_CARE	(-1)
 
+/* get and set the serial private data pointer helper functions */
+static inline void *usb_get_serial_data (struct usb_serial *serial)
+{
+	return serial->private;
+}
+
+static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+{
+	serial->private = data;
+}
 
 /**
  * usb_serial_device_type - a structure that defines a usb serial device
@@ -292,7 +312,7 @@
 	if (!port || 
 		port_paranoia_check (port, function) ||
 		serial_paranoia_check (port->serial, function)) {
-		/* then say that we dont have a valid usb_serial thing, which will
+		/* then say that we don't have a valid usb_serial thing, which will
 		 * end up genrating -ENODEV return values */ 
 		return NULL;
 	}
@@ -318,7 +338,7 @@
 
 /* Use our own dbg macro */
 #undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
 
 
 
diff -urN linux-2.4.22-bk12/drivers/usb/serial/usbserial.c linux-2.4.22-bk13/drivers/usb/serial/usbserial.c
--- linux-2.4.22-bk12/drivers/usb/serial/usbserial.c	2003-09-09 03:08:17.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/serial/usbserial.c	2003-09-09 03:08:29.000000000 -0700
@@ -556,7 +556,10 @@
 		else
 			generic_close(port, filp);
 		port->open_count = 0;
-		port->tty = NULL;
+		if (port->tty) {
+			port->tty->driver_data = NULL;
+			port->tty = NULL;
+		}
 	}
 
 	if (port->serial->type->owner)
@@ -1401,12 +1404,9 @@
 		for (i = 0; i < serial->num_ports; ++i) {
 			port = &serial->port[i];
 			down (&port->sem);
-			if (port->tty != NULL) {
-				while (port->open_count > 0) {
+			if (port->tty != NULL)
+				while (port->open_count > 0)
 					__serial_close(port, NULL);
-				}
-				port->tty->driver_data = NULL;
-			}
 			up (&port->sem);
 		}
 
diff -urN linux-2.4.22-bk12/drivers/usb/storage/unusual_devs.h linux-2.4.22-bk13/drivers/usb/storage/unusual_devs.h
--- linux-2.4.22-bk12/drivers/usb/storage/unusual_devs.h	2003-09-09 03:08:17.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/storage/unusual_devs.h	2003-09-09 03:08:29.000000000 -0700
@@ -618,6 +618,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Submitted by Joris Struyve <joris@struyve.be> */
+UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
+		"Medion",
+		"MD 7425",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY),
+
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
diff -urN linux-2.4.22-bk12/drivers/usb/stv680.c linux-2.4.22-bk13/drivers/usb/stv680.c
--- linux-2.4.22-bk12/drivers/usb/stv680.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-bk13/drivers/usb/stv680.c	2003-09-09 03:08:29.000000000 -0700
@@ -1243,7 +1243,6 @@
 				PDEBUG (2, "STV(e): VIDIOCSPICT failed");
 				return -EFAULT;
 			}
-			copy_from_user (&p, arg, sizeof (p));
 			PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette);
 
 			if (stv680_set_pict (stv680, &p))
diff -urN linux-2.4.22-bk12/drivers/usb/vicam.c linux-2.4.22-bk13/drivers/usb/vicam.c
--- linux-2.4.22-bk12/drivers/usb/vicam.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-bk13/drivers/usb/vicam.c	2003-09-09 03:08:29.000000000 -0700
@@ -969,18 +969,20 @@
 			if (cam->framebuf_read_start + count <=
 			    cam->framebuf_size) {
 				// count does not exceed available bytes
-				copy_to_user(buf,
-					     (cam->framebuf) +
-					     cam->framebuf_read_start, count);
+				if (copy_to_user(buf,
+						 (cam->framebuf) +
+						 cam->framebuf_read_start, count))
+					return -EFAULT;
 				cam->framebuf_read_start += count;
 				return count;
 			} else {
 				count =
 				    cam->framebuf_size -
 				    cam->framebuf_read_start;
-				copy_to_user(buf,
-					     (cam->framebuf) +
-					     cam->framebuf_read_start, count);
+				if (copy_to_user(buf,
+						 (cam->framebuf) +
+						 cam->framebuf_read_start, count))
+					return -EFAULT;
 				cam->framebuf_read_start = cam->framebuf_size;
 				return count;
 			}
@@ -1002,7 +1004,8 @@
 	if (count > cam->framebuf_size)
 		count = cam->framebuf_size;
 
-	copy_to_user(buf, cam->framebuf, count);
+	if (copy_to_user(buf, cam->framebuf, count))
+		return -EFAULT;
 
 	if (count != cam->framebuf_size)
 		cam->framebuf_read_start = count;
