|
@@ -520,10 +520,10 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
|
|
skb = alloc_can_err_skb(priv->netdev, &cf);
|
|
skb = alloc_can_err_skb(priv->netdev, &cf);
|
|
if (skb) {
|
|
if (skb) {
|
|
cf->can_id |= CAN_ERR_RESTARTED;
|
|
cf->can_id |= CAN_ERR_RESTARTED;
|
|
- netif_rx(skb);
|
|
|
|
|
|
|
|
stats->rx_packets++;
|
|
stats->rx_packets++;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
|
|
+ netif_rx(skb);
|
|
} else {
|
|
} else {
|
|
netdev_err(priv->netdev,
|
|
netdev_err(priv->netdev,
|
|
"No memory left for err_skb\n");
|
|
"No memory left for err_skb\n");
|
|
@@ -770,10 +770,9 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
|
|
|
|
|
|
priv->can.state = new_state;
|
|
priv->can.state = new_state;
|
|
|
|
|
|
- netif_rx(skb);
|
|
|
|
-
|
|
|
|
stats->rx_packets++;
|
|
stats->rx_packets++;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
|
|
+ netif_rx(skb);
|
|
}
|
|
}
|
|
|
|
|
|
static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
|
|
static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
|
|
@@ -805,10 +804,9 @@ static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
|
|
stats->rx_over_errors++;
|
|
stats->rx_over_errors++;
|
|
stats->rx_errors++;
|
|
stats->rx_errors++;
|
|
|
|
|
|
- netif_rx(skb);
|
|
|
|
-
|
|
|
|
stats->rx_packets++;
|
|
stats->rx_packets++;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
|
|
+ netif_rx(skb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -887,10 +885,9 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
|
|
cf->can_dlc);
|
|
cf->can_dlc);
|
|
}
|
|
}
|
|
|
|
|
|
- netif_rx(skb);
|
|
|
|
-
|
|
|
|
stats->rx_packets++;
|
|
stats->rx_packets++;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
stats->rx_bytes += cf->can_dlc;
|
|
|
|
+ netif_rx(skb);
|
|
}
|
|
}
|
|
|
|
|
|
static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
|
|
static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
|
|
@@ -1246,6 +1243,9 @@ static int kvaser_usb_close(struct net_device *netdev)
|
|
if (err)
|
|
if (err)
|
|
netdev_warn(netdev, "Cannot stop device, error %d\n", err);
|
|
netdev_warn(netdev, "Cannot stop device, error %d\n", err);
|
|
|
|
|
|
|
|
+ /* reset tx contexts */
|
|
|
|
+ kvaser_usb_unlink_tx_urbs(priv);
|
|
|
|
+
|
|
priv->can.state = CAN_STATE_STOPPED;
|
|
priv->can.state = CAN_STATE_STOPPED;
|
|
close_candev(priv->netdev);
|
|
close_candev(priv->netdev);
|
|
|
|
|
|
@@ -1294,12 +1294,14 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|
if (!urb) {
|
|
if (!urb) {
|
|
netdev_err(netdev, "No memory left for URBs\n");
|
|
netdev_err(netdev, "No memory left for URBs\n");
|
|
stats->tx_dropped++;
|
|
stats->tx_dropped++;
|
|
- goto nourbmem;
|
|
|
|
|
|
+ dev_kfree_skb(skb);
|
|
|
|
+ return NETDEV_TX_OK;
|
|
}
|
|
}
|
|
|
|
|
|
buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
|
|
buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
|
|
if (!buf) {
|
|
if (!buf) {
|
|
stats->tx_dropped++;
|
|
stats->tx_dropped++;
|
|
|
|
+ dev_kfree_skb(skb);
|
|
goto nobufmem;
|
|
goto nobufmem;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1334,6 +1336,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* This should never happen; it implies a flow control bug */
|
|
if (!context) {
|
|
if (!context) {
|
|
netdev_warn(netdev, "cannot find free context\n");
|
|
netdev_warn(netdev, "cannot find free context\n");
|
|
ret = NETDEV_TX_BUSY;
|
|
ret = NETDEV_TX_BUSY;
|
|
@@ -1364,9 +1367,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|
if (unlikely(err)) {
|
|
if (unlikely(err)) {
|
|
can_free_echo_skb(netdev, context->echo_index);
|
|
can_free_echo_skb(netdev, context->echo_index);
|
|
|
|
|
|
- skb = NULL; /* set to NULL to avoid double free in
|
|
|
|
- * dev_kfree_skb(skb) */
|
|
|
|
-
|
|
|
|
atomic_dec(&priv->active_tx_urbs);
|
|
atomic_dec(&priv->active_tx_urbs);
|
|
usb_unanchor_urb(urb);
|
|
usb_unanchor_urb(urb);
|
|
|
|
|
|
@@ -1388,8 +1388,6 @@ releasebuf:
|
|
kfree(buf);
|
|
kfree(buf);
|
|
nobufmem:
|
|
nobufmem:
|
|
usb_free_urb(urb);
|
|
usb_free_urb(urb);
|
|
-nourbmem:
|
|
|
|
- dev_kfree_skb(skb);
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1502,6 +1500,10 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
|
|
struct kvaser_usb_net_priv *priv;
|
|
struct kvaser_usb_net_priv *priv;
|
|
int i, err;
|
|
int i, err;
|
|
|
|
|
|
|
|
+ err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
|
|
netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
|
|
if (!netdev) {
|
|
if (!netdev) {
|
|
dev_err(&intf->dev, "Cannot alloc candev\n");
|
|
dev_err(&intf->dev, "Cannot alloc candev\n");
|
|
@@ -1606,9 +1608,6 @@ static int kvaser_usb_probe(struct usb_interface *intf,
|
|
|
|
|
|
usb_set_intfdata(intf, dev);
|
|
usb_set_intfdata(intf, dev);
|
|
|
|
|
|
- for (i = 0; i < MAX_NET_DEVICES; i++)
|
|
|
|
- kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
|
|
|
|
-
|
|
|
|
err = kvaser_usb_get_software_info(dev);
|
|
err = kvaser_usb_get_software_info(dev);
|
|
if (err) {
|
|
if (err) {
|
|
dev_err(&intf->dev,
|
|
dev_err(&intf->dev,
|