wip
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 8d6208c..9ec4fbf 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -423,11 +423,9 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
struct can_priv *priv = netdev_priv(dev);
BUG_ON(idx >= priv->echo_skb_max);
-
- /* check flag whether this packet has to be looped back */
- if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
- (skb->protocol != htons(ETH_P_CAN) &&
- skb->protocol != htons(ETH_P_CANFD))) {
+ if (WARN_ONCE(skb->protocol != htons(ETH_P_CAN) &&
+ skb->protocol != htons(ETH_P_CANFD),
+ "CAN function used with non ETH_P_CAN* skb->protocol\n")) {
kfree_skb(skb);
return;
}
@@ -471,7 +469,13 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
struct can_frame *cf = (struct can_frame *)skb->data;
u8 dlc = cf->can_dlc;
- netif_rx(priv->echo_skb[idx]);
+ /* check flag whether this packet has to be looped back */
+ if (!(dev->flags & IFF_ECHO) ||
+ skb->pkt_type != PACKET_LOOPBACK ) {
+ kfree_skb(skb);
+ else
+ netif_rx(priv->echo_skb[idx]);
+
priv->echo_skb[idx] = NULL;
return dlc;
@@ -685,11 +689,8 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
struct can_priv *priv;
int size;
- if (echo_skb_max)
- size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) +
- echo_skb_max * sizeof(struct sk_buff *);
- else
- size = sizeof_priv;
+ size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) +
+ echo_skb_max * sizeof(struct sk_buff *);
dev = alloc_netdev(size, "can%d", NET_NAME_UNKNOWN, can_setup);
if (!dev)
@@ -703,6 +704,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
priv->echo_skb = (void *)priv +
ALIGN(sizeof_priv, sizeof(struct sk_buff *));
}
+ skb_queue_head_init(&priv->echo_queue);
priv->state = CAN_STATE_STOPPED;
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 5f52709..4c98fcd 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -60,6 +60,7 @@ struct can_priv {
unsigned int echo_skb_max;
struct sk_buff **echo_skb;
+ struct sk_buff_head echo_queue;
#ifdef CONFIG_CAN_LEDS
struct led_trigger *tx_led_trig;