Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vcan: add CAN FD support

- move the length calculation from dlc to real length (using canfd_frame)
- allow to switch the driver between CAN and CAN FD (change of MTU)

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
41052ef6 1e0625fa

+20 -7
+20 -7
drivers/net/can/vcan.c
··· 70 70 71 71 static void vcan_rx(struct sk_buff *skb, struct net_device *dev) 72 72 { 73 - struct can_frame *cf = (struct can_frame *)skb->data; 73 + struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 74 74 struct net_device_stats *stats = &dev->stats; 75 75 76 76 stats->rx_packets++; 77 - stats->rx_bytes += cf->can_dlc; 77 + stats->rx_bytes += cfd->len; 78 78 79 - skb->protocol = htons(ETH_P_CAN); 80 79 skb->pkt_type = PACKET_BROADCAST; 81 80 skb->dev = dev; 82 81 skb->ip_summed = CHECKSUM_UNNECESSARY; ··· 85 86 86 87 static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) 87 88 { 88 - struct can_frame *cf = (struct can_frame *)skb->data; 89 + struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 89 90 struct net_device_stats *stats = &dev->stats; 90 91 int loop; 91 92 ··· 93 94 return NETDEV_TX_OK; 94 95 95 96 stats->tx_packets++; 96 - stats->tx_bytes += cf->can_dlc; 97 + stats->tx_bytes += cfd->len; 97 98 98 99 /* set flag whether this packet has to be looped back */ 99 100 loop = skb->pkt_type == PACKET_LOOPBACK; ··· 107 108 * CAN core already did the echo for us 108 109 */ 109 110 stats->rx_packets++; 110 - stats->rx_bytes += cf->can_dlc; 111 + stats->rx_bytes += cfd->len; 111 112 } 112 113 kfree_skb(skb); 113 114 return NETDEV_TX_OK; ··· 132 133 return NETDEV_TX_OK; 133 134 } 134 135 136 + static int vcan_change_mtu(struct net_device *dev, int new_mtu) 137 + { 138 + /* Do not allow changing the MTU while running */ 139 + if (dev->flags & IFF_UP) 140 + return -EBUSY; 141 + 142 + if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU) 143 + return -EINVAL; 144 + 145 + dev->mtu = new_mtu; 146 + return 0; 147 + } 148 + 135 149 static const struct net_device_ops vcan_netdev_ops = { 136 150 .ndo_start_xmit = vcan_tx, 151 + .ndo_change_mtu = vcan_change_mtu, 137 152 }; 138 153 139 154 static void vcan_setup(struct net_device *dev) 140 155 { 141 156 dev->type = ARPHRD_CAN; 142 - dev->mtu = sizeof(struct can_frame); 157 + dev->mtu = CAN_MTU; 143 158 dev->hard_header_len = 0; 144 159 dev->addr_len = 0; 145 160 dev->tx_queue_len = 0;