aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2007-03-30 07:11:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 16:28:38 -0400
commit5a9f4e338179e75e7e9b56293acb17023e342d81 (patch)
tree6fb9ca518235ae18d8cf238111d494a9fdee3f9e /drivers/usb
parent949ce47168a34618c3e24cb7dd4ab52233a4653c (diff)
USB: fix catc error handling
this driver ignores errors while starting the transmit queue. It will never be reported stopped as the completion handler won't run and it will never be started again as it will be considered started. This patch adds error handling. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/net/catc.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index ffec2e01b896..86e90c59d551 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -355,7 +355,7 @@ resubmit:
355 * Transmit routines. 355 * Transmit routines.
356 */ 356 */
357 357
358static void catc_tx_run(struct catc *catc) 358static int catc_tx_run(struct catc *catc)
359{ 359{
360 int status; 360 int status;
361 361
@@ -373,12 +373,14 @@ static void catc_tx_run(struct catc *catc)
373 catc->tx_ptr = 0; 373 catc->tx_ptr = 0;
374 374
375 catc->netdev->trans_start = jiffies; 375 catc->netdev->trans_start = jiffies;
376 return status;
376} 377}
377 378
378static void catc_tx_done(struct urb *urb) 379static void catc_tx_done(struct urb *urb)
379{ 380{
380 struct catc *catc = urb->context; 381 struct catc *catc = urb->context;
381 unsigned long flags; 382 unsigned long flags;
383 int r;
382 384
383 if (urb->status == -ECONNRESET) { 385 if (urb->status == -ECONNRESET) {
384 dbg("Tx Reset."); 386 dbg("Tx Reset.");
@@ -397,10 +399,13 @@ static void catc_tx_done(struct urb *urb)
397 399
398 spin_lock_irqsave(&catc->tx_lock, flags); 400 spin_lock_irqsave(&catc->tx_lock, flags);
399 401
400 if (catc->tx_ptr) 402 if (catc->tx_ptr) {
401 catc_tx_run(catc); 403 r = catc_tx_run(catc);
402 else 404 if (unlikely(r < 0))
405 clear_bit(TX_RUNNING, &catc->flags);
406 } else {
403 clear_bit(TX_RUNNING, &catc->flags); 407 clear_bit(TX_RUNNING, &catc->flags);
408 }
404 409
405 netif_wake_queue(catc->netdev); 410 netif_wake_queue(catc->netdev);
406 411
@@ -411,6 +416,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
411{ 416{
412 struct catc *catc = netdev_priv(netdev); 417 struct catc *catc = netdev_priv(netdev);
413 unsigned long flags; 418 unsigned long flags;
419 int r = 0;
414 char *tx_buf; 420 char *tx_buf;
415 421
416 spin_lock_irqsave(&catc->tx_lock, flags); 422 spin_lock_irqsave(&catc->tx_lock, flags);
@@ -421,8 +427,11 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
421 skb_copy_from_linear_data(skb, tx_buf + 2, skb->len); 427 skb_copy_from_linear_data(skb, tx_buf + 2, skb->len);
422 catc->tx_ptr += skb->len + 2; 428 catc->tx_ptr += skb->len + 2;
423 429
424 if (!test_and_set_bit(TX_RUNNING, &catc->flags)) 430 if (!test_and_set_bit(TX_RUNNING, &catc->flags)) {
425 catc_tx_run(catc); 431 r = catc_tx_run(catc);
432 if (r < 0)
433 clear_bit(TX_RUNNING, &catc->flags);
434 }
426 435
427 if ((catc->is_f5u011 && catc->tx_ptr) 436 if ((catc->is_f5u011 && catc->tx_ptr)
428 || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))) 437 || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
@@ -430,8 +439,10 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
430 439
431 spin_unlock_irqrestore(&catc->tx_lock, flags); 440 spin_unlock_irqrestore(&catc->tx_lock, flags);
432 441
433 catc->stats.tx_bytes += skb->len; 442 if (r >= 0) {
434 catc->stats.tx_packets++; 443 catc->stats.tx_bytes += skb->len;
444 catc->stats.tx_packets++;
445 }
435 446
436 dev_kfree_skb(skb); 447 dev_kfree_skb(skb);
437 448