Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Oliver Neukum and committed by
Greg Kroah-Hartman
5a9f4e33 949ce471

+19 -8
+19 -8
drivers/usb/net/catc.c
··· 355 355 * Transmit routines. 356 356 */ 357 357 358 - static void catc_tx_run(struct catc *catc) 358 + static int catc_tx_run(struct catc *catc) 359 359 { 360 360 int status; 361 361 ··· 373 373 catc->tx_ptr = 0; 374 374 375 375 catc->netdev->trans_start = jiffies; 376 + return status; 376 377 } 377 378 378 379 static void catc_tx_done(struct urb *urb) 379 380 { 380 381 struct catc *catc = urb->context; 381 382 unsigned long flags; 383 + int r; 382 384 383 385 if (urb->status == -ECONNRESET) { 384 386 dbg("Tx Reset."); ··· 399 397 400 398 spin_lock_irqsave(&catc->tx_lock, flags); 401 399 402 - if (catc->tx_ptr) 403 - catc_tx_run(catc); 404 - else 400 + if (catc->tx_ptr) { 401 + r = catc_tx_run(catc); 402 + if (unlikely(r < 0)) 403 + clear_bit(TX_RUNNING, &catc->flags); 404 + } else { 405 405 clear_bit(TX_RUNNING, &catc->flags); 406 + } 406 407 407 408 netif_wake_queue(catc->netdev); 408 409 ··· 416 411 { 417 412 struct catc *catc = netdev_priv(netdev); 418 413 unsigned long flags; 414 + int r = 0; 419 415 char *tx_buf; 420 416 421 417 spin_lock_irqsave(&catc->tx_lock, flags); ··· 427 421 skb_copy_from_linear_data(skb, tx_buf + 2, skb->len); 428 422 catc->tx_ptr += skb->len + 2; 429 423 430 - if (!test_and_set_bit(TX_RUNNING, &catc->flags)) 431 - catc_tx_run(catc); 424 + if (!test_and_set_bit(TX_RUNNING, &catc->flags)) { 425 + r = catc_tx_run(catc); 426 + if (r < 0) 427 + clear_bit(TX_RUNNING, &catc->flags); 428 + } 432 429 433 430 if ((catc->is_f5u011 && catc->tx_ptr) 434 431 || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))) ··· 439 430 440 431 spin_unlock_irqrestore(&catc->tx_lock, flags); 441 432 442 - catc->stats.tx_bytes += skb->len; 443 - catc->stats.tx_packets++; 433 + if (r >= 0) { 434 + catc->stats.tx_bytes += skb->len; 435 + catc->stats.tx_packets++; 436 + } 444 437 445 438 dev_kfree_skb(skb); 446 439