diff options
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 97 |
1 files changed, 59 insertions, 38 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4f8282ad7720..88a2c7dce335 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -69,6 +69,7 @@ struct usb_serial_driver usb_serial_generic_device = { | |||
69 | .shutdown = usb_serial_generic_shutdown, | 69 | .shutdown = usb_serial_generic_shutdown, |
70 | .throttle = usb_serial_generic_throttle, | 70 | .throttle = usb_serial_generic_throttle, |
71 | .unthrottle = usb_serial_generic_unthrottle, | 71 | .unthrottle = usb_serial_generic_unthrottle, |
72 | .resume = usb_serial_generic_resume, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int generic_probe(struct usb_interface *interface, | 75 | static int generic_probe(struct usb_interface *interface, |
@@ -169,6 +170,23 @@ static void generic_cleanup (struct usb_serial_port *port) | |||
169 | } | 170 | } |
170 | } | 171 | } |
171 | 172 | ||
173 | int usb_serial_generic_resume(struct usb_serial *serial) | ||
174 | { | ||
175 | struct usb_serial_port *port; | ||
176 | int i, c = 0, r; | ||
177 | |||
178 | for (i = 0; i < serial->num_ports; i++) { | ||
179 | port = serial->port[i]; | ||
180 | if (port->open_count && port->read_urb) { | ||
181 | r = usb_submit_urb(port->read_urb, GFP_NOIO); | ||
182 | if (r < 0) | ||
183 | c++; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return c ? -EIO : 0; | ||
188 | } | ||
189 | |||
172 | void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) | 190 | void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) |
173 | { | 191 | { |
174 | dbg("%s - port %d", __FUNCTION__, port->number); | 192 | dbg("%s - port %d", __FUNCTION__, port->number); |
@@ -263,79 +281,82 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
263 | return (chars); | 281 | return (chars); |
264 | } | 282 | } |
265 | 283 | ||
266 | /* Push data to tty layer and resubmit the bulk read URB */ | 284 | |
267 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | 285 | static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) |
268 | { | 286 | { |
269 | struct usb_serial *serial = port->serial; | ||
270 | struct urb *urb = port->read_urb; | 287 | struct urb *urb = port->read_urb; |
271 | struct tty_struct *tty = port->tty; | 288 | struct usb_serial *serial = port->serial; |
272 | int result; | 289 | int result; |
273 | 290 | ||
274 | /* Push data to tty */ | ||
275 | if (tty && urb->actual_length) { | ||
276 | tty_buffer_request_room(tty, urb->actual_length); | ||
277 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); | ||
278 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ | ||
279 | } | ||
280 | |||
281 | /* Continue reading from device */ | 291 | /* Continue reading from device */ |
282 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 292 | usb_fill_bulk_urb (urb, serial->dev, |
283 | usb_rcvbulkpipe (serial->dev, | 293 | usb_rcvbulkpipe (serial->dev, |
284 | port->bulk_in_endpointAddress), | 294 | port->bulk_in_endpointAddress), |
285 | port->read_urb->transfer_buffer, | 295 | urb->transfer_buffer, |
286 | port->read_urb->transfer_buffer_length, | 296 | urb->transfer_buffer_length, |
287 | ((serial->type->read_bulk_callback) ? | 297 | ((serial->type->read_bulk_callback) ? |
288 | serial->type->read_bulk_callback : | 298 | serial->type->read_bulk_callback : |
289 | usb_serial_generic_read_bulk_callback), port); | 299 | usb_serial_generic_read_bulk_callback), port); |
290 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 300 | result = usb_submit_urb(urb, mem_flags); |
291 | if (result) | 301 | if (result) |
292 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 302 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); |
293 | } | 303 | } |
294 | 304 | ||
305 | /* Push data to tty layer and resubmit the bulk read URB */ | ||
306 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | ||
307 | { | ||
308 | struct urb *urb = port->read_urb; | ||
309 | struct tty_struct *tty = port->tty; | ||
310 | int room; | ||
311 | |||
312 | /* Push data to tty */ | ||
313 | if (tty && urb->actual_length) { | ||
314 | room = tty_buffer_request_room(tty, urb->actual_length); | ||
315 | if (room) { | ||
316 | tty_insert_flip_string(tty, urb->transfer_buffer, room); | ||
317 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ | ||
318 | } | ||
319 | } | ||
320 | |||
321 | resubmit_read_urb(port, GFP_ATOMIC); | ||
322 | } | ||
323 | |||
295 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | 324 | void usb_serial_generic_read_bulk_callback (struct urb *urb) |
296 | { | 325 | { |
297 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 326 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
298 | unsigned char *data = urb->transfer_buffer; | 327 | unsigned char *data = urb->transfer_buffer; |
299 | int is_throttled; | 328 | int status = urb->status; |
300 | unsigned long flags; | ||
301 | 329 | ||
302 | dbg("%s - port %d", __FUNCTION__, port->number); | 330 | dbg("%s - port %d", __FUNCTION__, port->number); |
303 | 331 | ||
304 | if (urb->status) { | 332 | if (unlikely(status != 0)) { |
305 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 333 | dbg("%s - nonzero read bulk status received: %d", |
334 | __FUNCTION__, status); | ||
306 | return; | 335 | return; |
307 | } | 336 | } |
308 | 337 | ||
309 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 338 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
310 | 339 | ||
311 | /* Throttle the device if requested by tty */ | 340 | /* Throttle the device if requested by tty */ |
312 | if (urb->actual_length) { | 341 | spin_lock(&port->lock); |
313 | spin_lock_irqsave(&port->lock, flags); | 342 | if (!(port->throttled = port->throttle_req)) |
314 | is_throttled = port->throttled = port->throttle_req; | 343 | /* Handle data and continue reading from device */ |
315 | spin_unlock_irqrestore(&port->lock, flags); | 344 | flush_and_resubmit_read_urb(port); |
316 | if (is_throttled) { | 345 | spin_unlock(&port->lock); |
317 | /* Let the received data linger in the read URB; | ||
318 | * usb_serial_generic_unthrottle() will pick it | ||
319 | * up later. */ | ||
320 | dbg("%s - throttling device", __FUNCTION__); | ||
321 | return; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /* Handle data and continue reading from device */ | ||
326 | flush_and_resubmit_read_urb(port); | ||
327 | } | 346 | } |
328 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 347 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
329 | 348 | ||
330 | void usb_serial_generic_write_bulk_callback (struct urb *urb) | 349 | void usb_serial_generic_write_bulk_callback (struct urb *urb) |
331 | { | 350 | { |
332 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 351 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
352 | int status = urb->status; | ||
333 | 353 | ||
334 | dbg("%s - port %d", __FUNCTION__, port->number); | 354 | dbg("%s - port %d", __FUNCTION__, port->number); |
335 | 355 | ||
336 | port->write_urb_busy = 0; | 356 | port->write_urb_busy = 0; |
337 | if (urb->status) { | 357 | if (status) { |
338 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 358 | dbg("%s - nonzero write bulk status received: %d", |
359 | __FUNCTION__, status); | ||
339 | return; | 360 | return; |
340 | } | 361 | } |
341 | 362 | ||
@@ -370,8 +391,8 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port) | |||
370 | spin_unlock_irqrestore(&port->lock, flags); | 391 | spin_unlock_irqrestore(&port->lock, flags); |
371 | 392 | ||
372 | if (was_throttled) { | 393 | if (was_throttled) { |
373 | /* Handle pending data and resume reading from device */ | 394 | /* Resume reading from device */ |
374 | flush_and_resubmit_read_urb(port); | 395 | resubmit_read_urb(port, GFP_KERNEL); |
375 | } | 396 | } |
376 | } | 397 | } |
377 | 398 | ||