summaryrefslogtreecommitdiff
path: root/drivers/net/usb/raw_ip_net.c
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2012-02-10 21:00:10 -0800
committerSimone Willett <swillett@nvidia.com>2012-04-16 14:06:00 -0700
commit5847468a3ad998d65696446742a30f97619c954e (patch)
tree9f401fa978ccfc951a7d30a5330afa36f658eab9 /drivers/net/usb/raw_ip_net.c
parentb562e1901abf766e863e0790b06bdc9bdc309172 (diff)
net: usb: raw-ip: do not free skb if TX_BUSY flag set
Consume skb buffers only in success case. In fatal error case stop tx transmission instead. This prevents many retries and possible kernel crash. Bug 937178 Signed-off-by: Vinayak Pane <vpane@nvidia.com> Reviewed-on: http://git-master/r/83290 (cherry picked from commit 974ffdc61f26d86744e1a7b1003117da50df9020) Change-Id: Ib2b982c0cea91d2ba5e30c04869c4f22dca7ed31 Reviewed-on: http://git-master/r/96331 Tested-by: Vinayak Pane <vpane@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Steve Lin <stlin@nvidia.com>
Diffstat (limited to 'drivers/net/usb/raw_ip_net.c')
-rw-r--r--drivers/net/usb/raw_ip_net.c25
1 files changed, 9 insertions, 16 deletions
diff --git a/drivers/net/usb/raw_ip_net.c b/drivers/net/usb/raw_ip_net.c
index 35b696966479..1b32a0c7ba12 100644
--- a/drivers/net/usb/raw_ip_net.c
+++ b/drivers/net/usb/raw_ip_net.c
@@ -490,6 +490,7 @@ static netdev_tx_t baseband_usb_netdev_start_xmit(
if (err < 0) {
pr_err("tx urb submit error\n");
usb->stats.tx_errors++;
+ netif_stop_queue(dev);
return NETDEV_TX_BUSY;
}
@@ -748,7 +749,6 @@ static int usb_net_raw_ip_tx_urb_submit(struct baseband_usb *usb,
}
if (!usb->usb.interface) {
pr_err("usb interface disconnected - not submitting tx urb\n");
- kfree_skb(skb);
return -EINVAL;
}
@@ -756,14 +756,12 @@ static int usb_net_raw_ip_tx_urb_submit(struct baseband_usb *usb,
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
pr_err("usb_alloc_urb() failed\n");
- kfree_skb(skb);
return -ENOMEM;
}
buf = kzalloc(skb->len - 14, GFP_ATOMIC);
if (!buf) {
pr_err("usb buffer kzalloc() failed\n");
usb_free_urb(urb);
- kfree_skb(skb);
return -ENOMEM;
}
err = skb_copy_bits(skb, 14, buf, skb->len - 14);
@@ -771,7 +769,6 @@ static int usb_net_raw_ip_tx_urb_submit(struct baseband_usb *usb,
pr_err("skb_copy_bits() failed - %d\n", err);
kfree(buf);
usb_free_urb(urb);
- kfree_skb(skb);
return err;
}
usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.out,
@@ -806,23 +803,19 @@ static void usb_net_raw_ip_tx_urb_work(struct work_struct *work)
return;
}
+ /* check if usb interface disconnected */
+ if (!usb->usb.interface) {
+ pr_err("%s: not submitting tx urb %p -interface disconnected\n",
+ __func__, urb);
+ return;
+ }
+
/* submit queued tx urb(s) */
while ((urb = usb_get_from_anchor(&usb->usb.tx_urb_deferred))
!= (struct urb *) 0) {
/* decrement count from usb_get_from_anchor() */
usb_free_urb(urb);
- /* check if usb interface disconnected */
- if (!usb->usb.interface) {
- pr_err("%s: not submitting tx urb %p"
- " - interface disconnected\n",
- __func__, urb);
- if (urb->transfer_buffer) {
- kfree(urb->transfer_buffer);
- urb->transfer_buffer = (void *) 0;
- }
- usb_free_urb(urb);
- continue;
- }
+
/* autoresume before tx */
usb_mark_last_busy(usb->usb.device);
err = usb_autopm_get_interface(usb->usb.interface);