aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2007-03-30 13:11:00 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 13:28:38 -0700
commit5a9f4e338179e75e7e9b56293acb17023e342d81 (patch)
tree6fb9ca518235ae18d8cf238111d494a9fdee3f9e
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>
-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 ffec2e01b89..86e90c59d55 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -355,7 +355,7 @@ resubmit:
* Transmit routines.
*/
-static void catc_tx_run(struct catc *catc)
+static int catc_tx_run(struct catc *catc)
{
int status;
@@ -373,12 +373,14 @@ static void catc_tx_run(struct catc *catc)
catc->tx_ptr = 0;
catc->netdev->trans_start = jiffies;
+ return status;
}
static void catc_tx_done(struct urb *urb)
{
struct catc *catc = urb->context;
unsigned long flags;
+ int r;
if (urb->status == -ECONNRESET) {
dbg("Tx Reset.");
@@ -397,10 +399,13 @@ static void catc_tx_done(struct urb *urb)
spin_lock_irqsave(&catc->tx_lock, flags);
- if (catc->tx_ptr)
- catc_tx_run(catc);
- else
+ if (catc->tx_ptr) {
+ r = catc_tx_run(catc);
+ if (unlikely(r < 0))
+ clear_bit(TX_RUNNING, &catc->flags);
+ } else {
clear_bit(TX_RUNNING, &catc->flags);
+ }
netif_wake_queue(catc->netdev);
@@ -411,6 +416,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct catc *catc = netdev_priv(netdev);
unsigned long flags;
+ int r = 0;
char *tx_buf;
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)
skb_copy_from_linear_data(skb, tx_buf + 2, skb->len);
catc->tx_ptr += skb->len + 2;
- if (!test_and_set_bit(TX_RUNNING, &catc->flags))
- catc_tx_run(catc);
+ if (!test_and_set_bit(TX_RUNNING, &catc->flags)) {
+ r = catc_tx_run(catc);
+ if (r < 0)
+ clear_bit(TX_RUNNING, &catc->flags);
+ }
if ((catc->is_f5u011 && catc->tx_ptr)
|| (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)
spin_unlock_irqrestore(&catc->tx_lock, flags);
- catc->stats.tx_bytes += skb->len;
- catc->stats.tx_packets++;
+ if (r >= 0) {
+ catc->stats.tx_bytes += skb->len;
+ catc->stats.tx_packets++;
+ }
dev_kfree_skb(skb);