Commit c2ab7ac2 authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by David S. Miller

can: Fix can_send() handling on dev_queue_xmit() failures

The tx packet counting and the local loopback of CAN frames should
only happen in the case that the CAN frame has been enqueued to the
netdevice tx queue successfully.

Thanks to Andre Naujoks <nautsch@gmail.com> for reporting this issue.
Signed-off-by: default avatarOliver Hartkopp <oliver@hartkopp.net>
Signed-off-by: default avatarUrs Thuermann <urs@isnogud.escape.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33f9936b
...@@ -208,6 +208,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol) ...@@ -208,6 +208,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
*/ */
int can_send(struct sk_buff *skb, int loop) int can_send(struct sk_buff *skb, int loop)
{ {
struct sk_buff *newskb = NULL;
int err; int err;
if (skb->dev->type != ARPHRD_CAN) { if (skb->dev->type != ARPHRD_CAN) {
...@@ -244,8 +245,7 @@ int can_send(struct sk_buff *skb, int loop) ...@@ -244,8 +245,7 @@ int can_send(struct sk_buff *skb, int loop)
* If the interface is not capable to do loopback * If the interface is not capable to do loopback
* itself, we do it here. * itself, we do it here.
*/ */
struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); newskb = skb_clone(skb, GFP_ATOMIC);
if (!newskb) { if (!newskb) {
kfree_skb(skb); kfree_skb(skb);
return -ENOMEM; return -ENOMEM;
...@@ -254,7 +254,6 @@ int can_send(struct sk_buff *skb, int loop) ...@@ -254,7 +254,6 @@ int can_send(struct sk_buff *skb, int loop)
newskb->sk = skb->sk; newskb->sk = skb->sk;
newskb->ip_summed = CHECKSUM_UNNECESSARY; newskb->ip_summed = CHECKSUM_UNNECESSARY;
newskb->pkt_type = PACKET_BROADCAST; newskb->pkt_type = PACKET_BROADCAST;
netif_rx(newskb);
} }
} else { } else {
/* indication for the CAN driver: no loopback required */ /* indication for the CAN driver: no loopback required */
...@@ -266,11 +265,20 @@ int can_send(struct sk_buff *skb, int loop) ...@@ -266,11 +265,20 @@ int can_send(struct sk_buff *skb, int loop)
if (err > 0) if (err > 0)
err = net_xmit_errno(err); err = net_xmit_errno(err);
if (err) {
if (newskb)
kfree_skb(newskb);
return err;
}
if (newskb)
netif_rx(newskb);
/* update statistics */ /* update statistics */
can_stats.tx_frames++; can_stats.tx_frames++;
can_stats.tx_frames_delta++; can_stats.tx_frames_delta++;
return err; return 0;
} }
EXPORT_SYMBOL(can_send); EXPORT_SYMBOL(can_send);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment