diff options
Diffstat (limited to 'drivers/net/can/vxcan.c')
-rw-r--r-- | drivers/net/can/vxcan.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 8861a7d875e7..26a472d2ea58 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -9,6 +9,7 @@ * Copyright (c) 2017 Oliver Hartkopp <socketcan@hartkopp.net> */ +#include <linux/ethtool.h> #include <linux/module.h> #include <linux/init.h> #include <linux/netdevice.h> @@ -33,28 +34,34 @@ struct vxcan_priv { struct net_device __rcu *peer; }; -static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev) { struct vxcan_priv *priv = netdev_priv(dev); struct net_device *peer; - struct canfd_frame *cfd = (struct canfd_frame *)skb->data; struct net_device_stats *peerstats, *srcstats = &dev->stats; - u8 len; + struct sk_buff *skb; + unsigned int len; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dropped_invalid_skb(dev, oskb)) return NETDEV_TX_OK; rcu_read_lock(); peer = rcu_dereference(priv->peer); if (unlikely(!peer)) { - kfree_skb(skb); + kfree_skb(oskb); dev->stats.tx_dropped++; goto out_unlock; } - skb = can_create_echo_skb(skb); - if (!skb) + skb_tx_timestamp(oskb); + + skb = skb_clone(oskb, GFP_ATOMIC); + if (skb) { + consume_skb(oskb); + } else { + kfree_skb(oskb); goto out_unlock; + } /* reset CAN GW hop counter */ skb->csum_start = 0; @@ -62,8 +69,8 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev) skb->dev = peer; skb->ip_summed = CHECKSUM_UNNECESSARY; - len = cfd->len; - if (netif_rx_ni(skb) == NET_RX_SUCCESS) { + len = can_skb_get_data_len(skb); + if (netif_rx(skb) == NET_RX_SUCCESS) { srcstats->tx_packets++; srcstats->tx_bytes += len; peerstats = &peer->stats; @@ -124,7 +131,8 @@ static int vxcan_change_mtu(struct net_device *dev, int new_mtu) if (dev->flags & IFF_UP) return -EBUSY; - if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU) + if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU && + !can_is_canxl_dev_mtu(new_mtu)) return -EINVAL; dev->mtu = new_mtu; @@ -139,6 +147,10 @@ static const struct net_device_ops vxcan_netdev_ops = { .ndo_change_mtu = vxcan_change_mtu, }; +static const struct ethtool_ops vxcan_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + static void vxcan_setup(struct net_device *dev) { struct can_ml_priv *can_ml; @@ -148,8 +160,9 @@ static void vxcan_setup(struct net_device *dev) dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; - dev->flags = (IFF_NOARP|IFF_ECHO); + dev->flags = IFF_NOARP; dev->netdev_ops = &vxcan_netdev_ops; + dev->ethtool_ops = &vxcan_ethtool_ops; dev->needs_free_netdev = true; can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN); |