[kernel/f14] usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)

Dave Jones davej at fedoraproject.org
Tue Oct 11 14:26:10 UTC 2011


commit 7e156f0d654c23ccecbe62e81a6dfaf526fe6fb1
Author: Dave Jones <davej at redhat.com>
Date:   Tue Oct 11 10:24:49 2011 -0400

    usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)

 kernel.spec           |    8 +++
 usb-wwan-ioctls.patch |  136 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+), 0 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index b709489..a90d5e1 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -673,6 +673,8 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch
 
 Patch800: linux-2.6-crash-driver.patch
 
+Patch1000: usb-wwan-ioctls.patch
+
 # crypto/
 
 # virt + ksm patches
@@ -1453,6 +1455,9 @@ ApplyPatch create-sys-fs-cgroup-to-mount-cgroupfs-on.patch
 # /dev/crash driver.
 ApplyPatch linux-2.6-crash-driver.patch
 
+# usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
+ApplyPatch usb-wwan-ioctls.patch
+
 # Hack e1000e to work on Montevina SDV
 ApplyPatch linux-2.6-e1000-ich9-montevina.patch
 
@@ -2265,6 +2270,9 @@ fi
 # and build.
 
 %changelog
+* Tue Oct 11 2011 Dave Jones <davej at redhat.com>
+- usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
+
 * Fri Sep 23 2011 Josh Boyer <jwboyer at redhat.com> 2.6.35.14-98
 - CVE-2011-1161 CVE-2011-1161: tpm: infoleaks
 
diff --git a/usb-wwan-ioctls.patch b/usb-wwan-ioctls.patch
new file mode 100644
index 0000000..d2e6f96
--- /dev/null
+++ b/usb-wwan-ioctls.patch
@@ -0,0 +1,136 @@
+commit 02303f73373aa1da19dbec510ec5a4e2576f9610
+Author: Dan Williams <dcbw at redhat.com>
+Date:   Fri Nov 19 16:04:00 2010 -0600
+
+    usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
+    
+    Some devices (ex ZTE 2726) simply don't respond at all when data is sent
+    to some of their USB interfaces.  The data gets stuck in the TTYs queue
+    and sits there until close(2), which them blocks because closing_wait
+    defaults to 30 seconds (even though the fd is O_NONBLOCK).  This is
+    rarely desired.  Implement the standard mechanism to adjust closing_wait
+    and let applications handle it how they want to.
+    
+    Signed-off-by: Dan Williams <dcbw at redhat.com>
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 2297fb1..2a56cc3 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -989,6 +989,7 @@ static struct usb_serial_driver option_1port_device = {
+ 	.set_termios       = usb_wwan_set_termios,
+ 	.tiocmget          = usb_wwan_tiocmget,
+ 	.tiocmset          = usb_wwan_tiocmset,
++	.ioctl             = usb_wwan_ioctl,
+ 	.attach            = usb_wwan_startup,
+ 	.disconnect        = usb_wwan_disconnect,
+ 	.release           = usb_wwan_release,
+diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
+index 2be298a..3ab77c5 100644
+--- a/drivers/usb/serial/usb-wwan.h
++++ b/drivers/usb/serial/usb-wwan.h
+@@ -18,6 +18,8 @@ extern void usb_wwan_set_termios(struct tty_struct *tty,
+ extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
+ extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+ 			     unsigned int set, unsigned int clear);
++extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
++			  unsigned int cmd, unsigned long arg);
+ extern int usb_wwan_send_setup(struct usb_serial_port *port);
+ extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
+ 			  const unsigned char *buf, int count);
+diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
+index fbc9467..660b7ca 100644
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -33,6 +33,7 @@
+ #include <linux/bitops.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
++#include <linux/serial.h>
+ #include "usb-wwan.h"
+ 
+ static int debug;
+@@ -123,6 +124,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+ }
+ EXPORT_SYMBOL(usb_wwan_tiocmset);
+ 
++static int get_serial_info(struct usb_serial_port *port,
++			   struct serial_struct __user *retinfo)
++{
++	struct serial_struct tmp;
++
++	if (!retinfo)
++		return -EFAULT;
++
++	memset(&tmp, 0, sizeof(tmp));
++	tmp.line            = port->serial->minor;
++	tmp.port            = port->number;
++	tmp.baud_base       = tty_get_baud_rate(port->port.tty);
++	tmp.close_delay	    = port->port.close_delay / 10;
++	tmp.closing_wait    = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
++				 ASYNC_CLOSING_WAIT_NONE :
++				 port->port.closing_wait / 10;
++
++	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
++		return -EFAULT;
++	return 0;
++}
++
++static int set_serial_info(struct usb_serial_port *port,
++			   struct serial_struct __user *newinfo)
++{
++	struct serial_struct new_serial;
++	unsigned int closing_wait, close_delay;
++	int retval = 0;
++
++	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
++		return -EFAULT;
++
++	close_delay = new_serial.close_delay * 10;
++	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
++			ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
++
++	mutex_lock(&port->port.mutex);
++
++	if (!capable(CAP_SYS_ADMIN)) {
++		if ((close_delay != port->port.close_delay) ||
++		    (closing_wait != port->port.closing_wait))
++			retval = -EPERM;
++		else
++			retval = -EOPNOTSUPP;
++	} else {
++		port->port.close_delay  = close_delay;
++		port->port.closing_wait = closing_wait;
++	}
++
++	mutex_unlock(&port->port.mutex);
++	return retval;
++}
++
++int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
++		   unsigned int cmd, unsigned long arg)
++{
++	struct usb_serial_port *port = tty->driver_data;
++
++	dbg("%s cmd 0x%04x", __func__, cmd);
++
++	switch (cmd) {
++	case TIOCGSERIAL:
++		return get_serial_info(port,
++				       (struct serial_struct __user *) arg);
++	case TIOCSSERIAL:
++		return set_serial_info(port,
++				       (struct serial_struct __user *) arg);
++	default:
++		break;
++	}
++
++	dbg("%s arg not supported", __func__);
++
++	return -ENOIOCTLCMD;
++}
++EXPORT_SYMBOL(usb_wwan_ioctl);
++
+ /* Write */
+ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
+ 		   const unsigned char *buf, int count)


More information about the scm-commits mailing list