aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/cypress_m8.c90
1 files changed, 75 insertions, 15 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 12a265c4a13b..e1173c1aee37 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -131,6 +131,7 @@ struct cypress_private {
131 int write_urb_in_use; /* write urb in use indicator */ 131 int write_urb_in_use; /* write urb in use indicator */
132 int write_urb_interval; /* interval to use for write urb */ 132 int write_urb_interval; /* interval to use for write urb */
133 int read_urb_interval; /* interval to use for read urb */ 133 int read_urb_interval; /* interval to use for read urb */
134 int comm_is_ok; /* true if communication is (still) ok */
134 int termios_initialized; 135 int termios_initialized;
135 __u8 line_control; /* holds dtr / rts value */ 136 __u8 line_control; /* holds dtr / rts value */
136 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ 137 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */
@@ -170,6 +171,7 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
170static int cypress_chars_in_buffer (struct usb_serial_port *port); 171static int cypress_chars_in_buffer (struct usb_serial_port *port);
171static void cypress_throttle (struct usb_serial_port *port); 172static void cypress_throttle (struct usb_serial_port *port);
172static void cypress_unthrottle (struct usb_serial_port *port); 173static void cypress_unthrottle (struct usb_serial_port *port);
174static void cypress_set_dead (struct usb_serial_port *port);
173static void cypress_read_int_callback (struct urb *urb, struct pt_regs *regs); 175static void cypress_read_int_callback (struct urb *urb, struct pt_regs *regs);
174static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs); 176static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs);
175/* baud helper functions */ 177/* baud helper functions */
@@ -290,6 +292,9 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
290 292
291 priv = usb_get_serial_port_data(port); 293 priv = usb_get_serial_port_data(port);
292 294
295 if (!priv->comm_is_ok)
296 return -ENODEV;
297
293 switch(cypress_request_type) { 298 switch(cypress_request_type) {
294 case CYPRESS_SET_CONFIG: 299 case CYPRESS_SET_CONFIG:
295 300
@@ -369,9 +374,10 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
369 374
370 } while (retval != 8 && retval != -ENODEV); 375 } while (retval != 8 && retval != -ENODEV);
371 376
372 if (retval != 8) 377 if (retval != 8) {
373 err("%s - failed sending serial line settings - %d", __FUNCTION__, retval); 378 err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
374 else { 379 cypress_set_dead(port);
380 } else {
375 spin_lock_irqsave(&priv->lock, flags); 381 spin_lock_irqsave(&priv->lock, flags);
376 priv->baud_rate = new_baudrate; 382 priv->baud_rate = new_baudrate;
377 priv->cbr_mask = baud_mask; 383 priv->cbr_mask = baud_mask;
@@ -396,6 +402,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
396 402
397 if (retval != 5) { 403 if (retval != 5) {
398 err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval); 404 err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
405 cypress_set_dead(port);
399 return retval; 406 return retval;
400 } else { 407 } else {
401 spin_lock_irqsave(&priv->lock, flags); 408 spin_lock_irqsave(&priv->lock, flags);
@@ -417,6 +424,24 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
417} /* cypress_serial_control */ 424} /* cypress_serial_control */
418 425
419 426
427static void cypress_set_dead(struct usb_serial_port *port)
428{
429 struct cypress_private *priv = usb_get_serial_port_data(port);
430 unsigned long flags;
431
432 spin_lock_irqsave(&priv->lock, flags);
433 if (!priv->comm_is_ok) {
434 spin_unlock_irqrestore(&priv->lock, flags);
435 return;
436 }
437 priv->comm_is_ok = 0;
438 spin_unlock_irqrestore(&priv->lock, flags);
439
440 err("cypress_m8 suspending failing port %d - interval might be too short",
441 port->number);
442}
443
444
420/* given a baud mask, it will return integer baud on success */ 445/* given a baud mask, it will return integer baud on success */
421static int mask_to_rate (unsigned mask) 446static int mask_to_rate (unsigned mask)
422{ 447{
@@ -478,6 +503,7 @@ static int generic_startup (struct usb_serial *serial)
478 if (!priv) 503 if (!priv)
479 return -ENOMEM; 504 return -ENOMEM;
480 505
506 priv->comm_is_ok = !0;
481 spin_lock_init(&priv->lock); 507 spin_lock_init(&priv->lock);
482 priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); 508 priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
483 if (priv->buf == NULL) { 509 if (priv->buf == NULL) {
@@ -595,6 +621,9 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
595 621
596 dbg("%s - port %d", __FUNCTION__, port->number); 622 dbg("%s - port %d", __FUNCTION__, port->number);
597 623
624 if (!priv->comm_is_ok)
625 return -EIO;
626
598 /* clear halts before open */ 627 /* clear halts before open */
599 usb_clear_halt(serial->dev, 0x81); 628 usb_clear_halt(serial->dev, 0x81);
600 usb_clear_halt(serial->dev, 0x02); 629 usb_clear_halt(serial->dev, 0x02);
@@ -639,6 +668,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
639 668
640 if (result){ 669 if (result){
641 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); 670 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
671 cypress_set_dead(port);
642 } 672 }
643 673
644 return result; 674 return result;
@@ -743,6 +773,9 @@ static void cypress_send(struct usb_serial_port *port)
743 struct cypress_private *priv = usb_get_serial_port_data(port); 773 struct cypress_private *priv = usb_get_serial_port_data(port);
744 unsigned long flags; 774 unsigned long flags;
745 775
776 if (!priv->comm_is_ok)
777 return;
778
746 dbg("%s - port %d", __FUNCTION__, port->number); 779 dbg("%s - port %d", __FUNCTION__, port->number);
747 dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size); 780 dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
748 781
@@ -825,6 +858,7 @@ send:
825 dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, 858 dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
826 result); 859 result);
827 priv->write_urb_in_use = 0; 860 priv->write_urb_in_use = 0;
861 cypress_set_dead(port);
828 } 862 }
829 863
830 spin_lock_irqsave(&priv->lock, flags); 864 spin_lock_irqsave(&priv->lock, flags);
@@ -1225,13 +1259,18 @@ static void cypress_unthrottle (struct usb_serial_port *port)
1225 priv->rx_flags = 0; 1259 priv->rx_flags = 0;
1226 spin_unlock_irqrestore(&priv->lock, flags); 1260 spin_unlock_irqrestore(&priv->lock, flags);
1227 1261
1262 if (!priv->comm_is_ok)
1263 return;
1264
1228 if (actually_throttled) { 1265 if (actually_throttled) {
1229 port->interrupt_in_urb->dev = port->serial->dev; 1266 port->interrupt_in_urb->dev = port->serial->dev;
1230 1267
1231 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1268 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1232 if (result) 1269 if (result) {
1233 dev_err(&port->dev, "%s - failed submitting read urb, " 1270 dev_err(&port->dev, "%s - failed submitting read urb, "
1234 "error %d\n", __FUNCTION__, result); 1271 "error %d\n", __FUNCTION__, result);
1272 cypress_set_dead(port);
1273 }
1235 } 1274 }
1236} 1275}
1237 1276
@@ -1251,9 +1290,22 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
1251 1290
1252 dbg("%s - port %d", __FUNCTION__, port->number); 1291 dbg("%s - port %d", __FUNCTION__, port->number);
1253 1292
1254 if (urb->status) { 1293 switch (urb->status) {
1255 dbg("%s - nonzero read status received: %d", __FUNCTION__, 1294 case 0: /* success */
1256 urb->status); 1295 break;
1296 case -ECONNRESET:
1297 case -ENOENT:
1298 case -ESHUTDOWN:
1299 /* precursor to disconnect so just go away */
1300 return;
1301 case -EPIPE:
1302 usb_clear_halt(port->serial->dev,0x81);
1303 break;
1304 default:
1305 /* something ugly is going on... */
1306 dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
1307 __FUNCTION__,urb->status);
1308 cypress_set_dead(port);
1257 return; 1309 return;
1258 } 1310 }
1259 1311
@@ -1354,7 +1406,7 @@ continue_read:
1354 1406
1355 /* Continue trying to always read... unless the port has closed. */ 1407 /* Continue trying to always read... unless the port has closed. */
1356 1408
1357 if (port->open_count > 0) { 1409 if (port->open_count > 0 && priv->comm_is_ok) {
1358 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, 1410 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
1359 usb_rcvintpipe(port->serial->dev, 1411 usb_rcvintpipe(port->serial->dev,
1360 port->interrupt_in_endpointAddress), 1412 port->interrupt_in_endpointAddress),
@@ -1362,10 +1414,12 @@ continue_read:
1362 port->interrupt_in_urb->transfer_buffer_length, 1414 port->interrupt_in_urb->transfer_buffer_length,
1363 cypress_read_int_callback, port, priv->read_urb_interval); 1415 cypress_read_int_callback, port, priv->read_urb_interval);
1364 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1416 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1365 if (result) 1417 if (result) {
1366 dev_err(&urb->dev->dev, "%s - failed resubmitting " 1418 dev_err(&urb->dev->dev, "%s - failed resubmitting "
1367 "read urb, error %d\n", __FUNCTION__, 1419 "read urb, error %d\n", __FUNCTION__,
1368 result); 1420 result);
1421 cypress_set_dead(port);
1422 }
1369 } 1423 }
1370 1424
1371 return; 1425 return;
@@ -1391,20 +1445,26 @@ static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
1391 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); 1445 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
1392 priv->write_urb_in_use = 0; 1446 priv->write_urb_in_use = 0;
1393 return; 1447 return;
1394 case -EPIPE: /* no break needed */ 1448 case -EPIPE: /* no break needed; clear halt and resubmit */
1449 if (!priv->comm_is_ok)
1450 break;
1395 usb_clear_halt(port->serial->dev, 0x02); 1451 usb_clear_halt(port->serial->dev, 0x02);
1396 default:
1397 /* error in the urb, so we have to resubmit it */ 1452 /* error in the urb, so we have to resubmit it */
1398 dbg("%s - Overflow in write", __FUNCTION__);
1399 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); 1453 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
1400 port->interrupt_out_urb->transfer_buffer_length = 1; 1454 port->interrupt_out_urb->transfer_buffer_length = 1;
1401 port->interrupt_out_urb->dev = port->serial->dev; 1455 port->interrupt_out_urb->dev = port->serial->dev;
1402 result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); 1456 result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
1403 if (result) 1457 if (!result)
1404 dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
1405 __FUNCTION__, result);
1406 else
1407 return; 1458 return;
1459 dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
1460 __FUNCTION__, result);
1461 cypress_set_dead(port);
1462 break;
1463 default:
1464 dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
1465 __FUNCTION__,urb->status);
1466 cypress_set_dead(port);
1467 break;
1408 } 1468 }
1409 1469
1410 priv->write_urb_in_use = 0; 1470 priv->write_urb_in_use = 0;