Title: [8208] trunk/drivers/usb/gadget/u_serial.c: bug[#5813]use work queue instead of tasklet to fix 'scheduling while atomic' problem,also low_latency mode is allowed
Revision
8208
Author
cliff
Date
2010-01-21 03:01:00 -0500 (Thu, 21 Jan 2010)

Log Message

bug[#5813]use work queue instead of tasklet to fix 'scheduling while atomic' problem,also low_latency mode is allowed

Modified Paths

Diff

Modified: trunk/drivers/usb/gadget/u_serial.c (8207 => 8208)


--- trunk/drivers/usb/gadget/u_serial.c	2010-01-21 07:20:44 UTC (rev 8207)
+++ trunk/drivers/usb/gadget/u_serial.c	2010-01-21 08:01:00 UTC (rev 8208)
@@ -105,7 +105,7 @@
 	struct list_head	read_pool;
 	struct list_head	read_queue;
 	unsigned		n_read;
-	struct tasklet_struct	push;
+	struct work_struct	push;
 
 	struct list_head	write_pool;
 	struct gs_buf		port_write_buf;
@@ -464,9 +464,9 @@
  * So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
  * can be buffered before the TTY layer's buffers (currently 64 KB).
  */
-static void gs_rx_push(unsigned long _port)
+static void gs_rx_push(struct work_struct *work)
 {
-	struct gs_port		*port = (void *)_port;
+	struct gs_port		*port = container_of(work, struct gs_port, push);
 	struct tty_struct	*tty;
 	struct list_head	*queue = &port->read_queue;
 	bool			disconnect = false;
@@ -560,7 +560,7 @@
 	if (!list_empty(queue) && tty) {
 		if (!test_bit(TTY_THROTTLED, &tty->flags)) {
 			if (do_push)
-				tasklet_schedule(&port->push);
+				schedule_work(&port->push);
 			else
 				pr_warning(PREFIX "%d: RX not scheduled?\n",
 					port->port_num);
@@ -581,7 +581,7 @@
 	/* Queue all received data until the tty layer is ready for it. */
 	spin_lock(&port->port_lock);
 	list_add_tail(&req->list, &port->read_queue);
-	tasklet_schedule(&port->push);
+	schedule_work(&port->push);
 	spin_unlock(&port->port_lock);
 }
 
@@ -783,6 +783,11 @@
 	port->open_count = 1;
 	port->openclose = false;
 
+	/* low_latency means ldiscs work in tasklet context, without
+	 * needing a workqueue schedule ... easier to keep up.
+	 */
+	tty->low_latency = 1;
+
 	/* if connected, start the I/O stream */
 	if (port->port_usb) {
 		struct gserial	*gser = port->port_usb;
@@ -970,7 +975,7 @@
 		 * rts/cts, or other handshaking with the host, but if the
 		 * read queue backs up enough we'll be NAKing OUT packets.
 		 */
-		tasklet_schedule(&port->push);
+		schedule_work(&port->push);
 		pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
 	}
 	spin_unlock_irqrestore(&port->port_lock, flags);
@@ -1023,7 +1028,7 @@
 	init_waitqueue_head(&port->close_wait);
 	init_waitqueue_head(&port->drain_wait);
 
-	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
+	INIT_WORK(&port->push, gs_rx_push);
 
 	INIT_LIST_HEAD(&port->read_pool);
 	INIT_LIST_HEAD(&port->read_queue);
@@ -1177,7 +1182,7 @@
 		ports[i].port = NULL;
 		mutex_unlock(&ports[i].lock);
 
-		tasklet_kill(&port->push);
+		flush_scheduled_work();
 
 		/* wait for old opens to finish */
 		wait_event(port->close_wait, gs_closed(port));
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to