Commit 41052ef6 authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde

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: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 1e0625fa
...@@ -70,13 +70,12 @@ MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)"); ...@@ -70,13 +70,12 @@ MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
static void vcan_rx(struct sk_buff *skb, struct net_device *dev) static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
{ {
struct can_frame *cf = (struct can_frame *)skb->data; struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats; struct net_device_stats *stats = &dev->stats;
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += cf->can_dlc; stats->rx_bytes += cfd->len;
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST; skb->pkt_type = PACKET_BROADCAST;
skb->dev = dev; skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
...@@ -86,7 +85,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev) ...@@ -86,7 +85,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
{ {
struct can_frame *cf = (struct can_frame *)skb->data; struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats; struct net_device_stats *stats = &dev->stats;
int loop; int loop;
...@@ -94,7 +93,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -94,7 +93,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
stats->tx_packets++; stats->tx_packets++;
stats->tx_bytes += cf->can_dlc; stats->tx_bytes += cfd->len;
/* set flag whether this packet has to be looped back */ /* set flag whether this packet has to be looped back */
loop = skb->pkt_type == PACKET_LOOPBACK; loop = skb->pkt_type == PACKET_LOOPBACK;
...@@ -108,7 +107,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -108,7 +107,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
* CAN core already did the echo for us * CAN core already did the echo for us
*/ */
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += cf->can_dlc; stats->rx_bytes += cfd->len;
} }
kfree_skb(skb); kfree_skb(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -133,14 +132,28 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -133,14 +132,28 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static int vcan_change_mtu(struct net_device *dev, int new_mtu)
{
/* Do not allow changing the MTU while running */
if (dev->flags & IFF_UP)
return -EBUSY;
if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
static const struct net_device_ops vcan_netdev_ops = { static const struct net_device_ops vcan_netdev_ops = {
.ndo_start_xmit = vcan_tx, .ndo_start_xmit = vcan_tx,
.ndo_change_mtu = vcan_change_mtu,
}; };
static void vcan_setup(struct net_device *dev) static void vcan_setup(struct net_device *dev)
{ {
dev->type = ARPHRD_CAN; dev->type = ARPHRD_CAN;
dev->mtu = sizeof(struct can_frame); dev->mtu = CAN_MTU;
dev->hard_header_len = 0; dev->hard_header_len = 0;
dev->addr_len = 0; dev->addr_len = 0;
dev->tx_queue_len = 0; dev->tx_queue_len = 0;
......
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