aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/serial/generic.c132
-rw-r--r--include/linux/usb/serial.h9
2 files changed, 62 insertions, 79 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index be52c748bccb..ad4823bbfa19 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -25,6 +25,8 @@
25 25
26static int debug; 26static int debug;
27 27
28#define MAX_TX_URBS 40
29
28#ifdef CONFIG_USB_SERIAL_GENERIC 30#ifdef CONFIG_USB_SERIAL_GENERIC
29 31
30static int generic_probe(struct usb_interface *interface, 32static int generic_probe(struct usb_interface *interface,
@@ -172,78 +174,63 @@ static int usb_serial_multi_urb_write(struct tty_struct *tty,
172 struct urb *urb; 174 struct urb *urb;
173 unsigned char *buffer; 175 unsigned char *buffer;
174 int status; 176 int status;
175 int towrite;
176 int bwrite = 0;
177
178 dbg("%s - port %d", __func__, port->number);
179
180 if (count == 0)
181 dbg("%s - write request of 0 bytes", __func__);
182 177
183 while (count > 0) { 178 spin_lock_irqsave(&port->lock, flags);
184 towrite = (count > port->bulk_out_size) ? 179 if (port->tx_urbs == MAX_TX_URBS) {
185 port->bulk_out_size : count;
186 spin_lock_irqsave(&port->lock, flags);
187 if (port->urbs_in_flight >
188 port->serial->type->max_in_flight_urbs) {
189 spin_unlock_irqrestore(&port->lock, flags);
190 dbg("%s - write limit hit", __func__);
191 return bwrite;
192 }
193 port->tx_bytes_flight += towrite;
194 port->urbs_in_flight++;
195 spin_unlock_irqrestore(&port->lock, flags); 180 spin_unlock_irqrestore(&port->lock, flags);
181 dbg("%s - write limit hit", __func__);
182 return 0;
183 }
184 port->tx_urbs++;
185 spin_unlock_irqrestore(&port->lock, flags);
196 186
197 buffer = kmalloc(towrite, GFP_ATOMIC); 187 urb = usb_alloc_urb(0, GFP_ATOMIC);
198 if (!buffer) { 188 if (!urb) {
199 dev_err(&port->dev, 189 dev_err(&port->dev, "%s - no free urbs available\n", __func__);
200 "%s ran out of kernel memory for urb ...\n", __func__); 190 status = -ENOMEM;
201 goto error_no_buffer; 191 goto err_urb;
202 } 192 }
203 193
204 urb = usb_alloc_urb(0, GFP_ATOMIC); 194 count = min_t(int, count, PAGE_SIZE);
205 if (!urb) { 195 buffer = kmalloc(count, GFP_ATOMIC);
206 dev_err(&port->dev, "%s - no more free urbs\n", 196 if (!buffer) {
197 dev_err(&port->dev, "%s - could not allocate buffer\n",
207 __func__); 198 __func__);
208 goto error_no_urb; 199 status = -ENOMEM;
209 } 200 goto err_buf;
201 }
210 202
211 /* Copy data */ 203 memcpy(buffer, buf, count);
212 memcpy(buffer, buf + bwrite, towrite); 204 usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
213 usb_serial_debug_data(debug, &port->dev, __func__, 205 usb_fill_bulk_urb(urb, port->serial->dev,
214 towrite, buffer);
215 /* fill the buffer and send it */
216 usb_fill_bulk_urb(urb, port->serial->dev,
217 usb_sndbulkpipe(port->serial->dev, 206 usb_sndbulkpipe(port->serial->dev,
218 port->bulk_out_endpointAddress), 207 port->bulk_out_endpointAddress),
219 buffer, towrite, 208 buffer, count,
220 port->serial->type->write_bulk_callback, port); 209 port->serial->type->write_bulk_callback, port);
221 210
222 status = usb_submit_urb(urb, GFP_ATOMIC); 211 status = usb_submit_urb(urb, GFP_ATOMIC);
223 if (status) { 212 if (status) {
224 dev_err(&port->dev, "%s - error submitting urb: %d\n", 213 dev_err(&port->dev, "%s - error submitting urb: %d\n",
225 __func__, status); 214 __func__, status);
226 goto error; 215 goto err;
227 }
228
229 /* This urb is the responsibility of the host driver now */
230 usb_free_urb(urb);
231 dbg("%s write: %d", __func__, towrite);
232 count -= towrite;
233 bwrite += towrite;
234 } 216 }
235 return bwrite; 217 spin_lock_irqsave(&port->lock, flags);
218 port->tx_bytes += urb->transfer_buffer_length;
219 spin_unlock_irqrestore(&port->lock, flags);
236 220
237error:
238 usb_free_urb(urb); 221 usb_free_urb(urb);
239error_no_urb: 222
223 return count;
224err:
240 kfree(buffer); 225 kfree(buffer);
241error_no_buffer: 226err_buf:
227 usb_free_urb(urb);
228err_urb:
242 spin_lock_irqsave(&port->lock, flags); 229 spin_lock_irqsave(&port->lock, flags);
243 port->urbs_in_flight--; 230 port->tx_urbs--;
244 port->tx_bytes_flight -= towrite;
245 spin_unlock_irqrestore(&port->lock, flags); 231 spin_unlock_irqrestore(&port->lock, flags);
246 return bwrite; 232
233 return status;
247} 234}
248 235
249/** 236/**
@@ -286,7 +273,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port)
286 } 273 }
287 274
288 spin_lock_irqsave(&port->lock, flags); 275 spin_lock_irqsave(&port->lock, flags);
289 port->tx_bytes_flight += count; 276 port->tx_bytes += count;
290 spin_unlock_irqrestore(&port->lock, flags); 277 spin_unlock_irqrestore(&port->lock, flags);
291 278
292 return count; 279 return count;
@@ -318,9 +305,8 @@ int usb_serial_generic_write(struct tty_struct *tty,
318 if (!count) 305 if (!count)
319 return 0; 306 return 0;
320 307
321 if (serial->type->max_in_flight_urbs) 308 if (serial->type->multi_urb_write)
322 return usb_serial_multi_urb_write(tty, port, 309 return usb_serial_multi_urb_write(tty, port, buf, count);
323 buf, count);
324 310
325 count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); 311 count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
326 result = usb_serial_generic_write_start(port); 312 result = usb_serial_generic_write_start(port);
@@ -337,7 +323,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
337 struct usb_serial_port *port = tty->driver_data; 323 struct usb_serial_port *port = tty->driver_data;
338 struct usb_serial *serial = port->serial; 324 struct usb_serial *serial = port->serial;
339 unsigned long flags; 325 unsigned long flags;
340 int room = 0; 326 int room;
341 327
342 dbg("%s - port %d", __func__, port->number); 328 dbg("%s - port %d", __func__, port->number);
343 329
@@ -345,14 +331,10 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
345 return 0; 331 return 0;
346 332
347 spin_lock_irqsave(&port->lock, flags); 333 spin_lock_irqsave(&port->lock, flags);
348 if (serial->type->max_in_flight_urbs) { 334 if (serial->type->multi_urb_write)
349 if (port->urbs_in_flight < serial->type->max_in_flight_urbs) 335 room = (MAX_TX_URBS - port->tx_urbs) * PAGE_SIZE;
350 room = port->bulk_out_size * 336 else
351 (serial->type->max_in_flight_urbs -
352 port->urbs_in_flight);
353 } else {
354 room = kfifo_avail(&port->write_fifo); 337 room = kfifo_avail(&port->write_fifo);
355 }
356 spin_unlock_irqrestore(&port->lock, flags); 338 spin_unlock_irqrestore(&port->lock, flags);
357 339
358 dbg("%s - returns %d", __func__, room); 340 dbg("%s - returns %d", __func__, room);
@@ -372,10 +354,10 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
372 return 0; 354 return 0;
373 355
374 spin_lock_irqsave(&port->lock, flags); 356 spin_lock_irqsave(&port->lock, flags);
375 if (serial->type->max_in_flight_urbs) 357 if (serial->type->multi_urb_write)
376 chars = port->tx_bytes_flight; 358 chars = port->tx_bytes;
377 else 359 else
378 chars = kfifo_len(&port->write_fifo) + port->tx_bytes_flight; 360 chars = kfifo_len(&port->write_fifo) + port->tx_bytes;
379 spin_unlock_irqrestore(&port->lock, flags); 361 spin_unlock_irqrestore(&port->lock, flags);
380 362
381 dbg("%s - returns %d", __func__, chars); 363 dbg("%s - returns %d", __func__, chars);
@@ -461,18 +443,16 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
461 443
462 dbg("%s - port %d", __func__, port->number); 444 dbg("%s - port %d", __func__, port->number);
463 445
464 if (port->serial->type->max_in_flight_urbs) { 446 if (port->serial->type->multi_urb_write) {
465 kfree(urb->transfer_buffer); 447 kfree(urb->transfer_buffer);
466 448
467 spin_lock_irqsave(&port->lock, flags); 449 spin_lock_irqsave(&port->lock, flags);
468 --port->urbs_in_flight; 450 port->tx_bytes -= urb->transfer_buffer_length;
469 port->tx_bytes_flight -= urb->transfer_buffer_length; 451 port->tx_urbs--;
470 if (port->urbs_in_flight < 0)
471 port->urbs_in_flight = 0;
472 spin_unlock_irqrestore(&port->lock, flags); 452 spin_unlock_irqrestore(&port->lock, flags);
473 } else { 453 } else {
474 spin_lock_irqsave(&port->lock, flags); 454 spin_lock_irqsave(&port->lock, flags);
475 port->tx_bytes_flight -= urb->transfer_buffer_length; 455 port->tx_bytes -= urb->transfer_buffer_length;
476 port->write_urb_busy = 0; 456 port->write_urb_busy = 0;
477 spin_unlock_irqrestore(&port->lock, flags); 457 spin_unlock_irqrestore(&port->lock, flags);
478 458
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index ff8872eba3ac..2a3283761600 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -60,6 +60,8 @@ enum port_dev_state {
60 * @write_urb: pointer to the bulk out struct urb for this port. 60 * @write_urb: pointer to the bulk out struct urb for this port.
61 * @write_fifo: kfifo used to buffer outgoing data 61 * @write_fifo: kfifo used to buffer outgoing data
62 * @write_urb_busy: port`s writing status 62 * @write_urb_busy: port`s writing status
63 * @tx_bytes: number of bytes currently in host stack queues
64 * @tx_urbs: number of urbs currently in host stack queues
63 * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this 65 * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
64 * port. 66 * port.
65 * @write_wait: a wait_queue_head_t used by the port. 67 * @write_wait: a wait_queue_head_t used by the port.
@@ -98,8 +100,8 @@ struct usb_serial_port {
98 int write_urb_busy; 100 int write_urb_busy;
99 __u8 bulk_out_endpointAddress; 101 __u8 bulk_out_endpointAddress;
100 102
101 int tx_bytes_flight; 103 int tx_bytes;
102 int urbs_in_flight; 104 int tx_urbs;
103 105
104 wait_queue_head_t write_wait; 106 wait_queue_head_t write_wait;
105 struct work_struct work; 107 struct work_struct work;
@@ -223,7 +225,8 @@ struct usb_serial_driver {
223 struct device_driver driver; 225 struct device_driver driver;
224 struct usb_driver *usb_driver; 226 struct usb_driver *usb_driver;
225 struct usb_dynids dynids; 227 struct usb_dynids dynids;
226 int max_in_flight_urbs; 228
229 unsigned char multi_urb_write:1;
227 230
228 size_t bulk_in_size; 231 size_t bulk_in_size;
229 size_t bulk_out_size; 232 size_t bulk_out_size;