diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2012-06-13 14:56:59 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2012-06-19 15:40:20 -0400 |
commit | 41052ef6dfe90e7639103a010f49d13dadc55a28 (patch) | |
tree | f0e4a8230dd94ea76f1a7255c10fea6aa708a6f2 /drivers | |
parent | 1e0625facab2e871472472b7df87d8fbe6caf75a (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/can/vcan.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index ea2d94285936..4f93c0be0053 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c | |||
@@ -70,13 +70,12 @@ MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)"); | |||
70 | 70 | ||
71 | static void vcan_rx(struct sk_buff *skb, struct net_device *dev) | 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 | struct net_device_stats *stats = &dev->stats; | 74 | struct net_device_stats *stats = &dev->stats; |
75 | 75 | ||
76 | stats->rx_packets++; | 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 | skb->pkt_type = PACKET_BROADCAST; | 79 | skb->pkt_type = PACKET_BROADCAST; |
81 | skb->dev = dev; | 80 | skb->dev = dev; |
82 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 81 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -86,7 +85,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev) | |||
86 | 85 | ||
87 | static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) | 86 | static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) |
88 | { | 87 | { |
89 | struct can_frame *cf = (struct can_frame *)skb->data; | 88 | struct canfd_frame *cfd = (struct canfd_frame *)skb->data; |
90 | struct net_device_stats *stats = &dev->stats; | 89 | struct net_device_stats *stats = &dev->stats; |
91 | int loop; | 90 | int loop; |
92 | 91 | ||
@@ -94,7 +93,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) | |||
94 | return NETDEV_TX_OK; | 93 | return NETDEV_TX_OK; |
95 | 94 | ||
96 | stats->tx_packets++; | 95 | stats->tx_packets++; |
97 | stats->tx_bytes += cf->can_dlc; | 96 | stats->tx_bytes += cfd->len; |
98 | 97 | ||
99 | /* set flag whether this packet has to be looped back */ | 98 | /* set flag whether this packet has to be looped back */ |
100 | loop = skb->pkt_type == PACKET_LOOPBACK; | 99 | 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 | * CAN core already did the echo for us | 107 | * CAN core already did the echo for us |
109 | */ | 108 | */ |
110 | stats->rx_packets++; | 109 | stats->rx_packets++; |
111 | stats->rx_bytes += cf->can_dlc; | 110 | stats->rx_bytes += cfd->len; |
112 | } | 111 | } |
113 | kfree_skb(skb); | 112 | kfree_skb(skb); |
114 | return NETDEV_TX_OK; | 113 | return NETDEV_TX_OK; |
@@ -133,14 +132,28 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) | |||
133 | return NETDEV_TX_OK; | 132 | return NETDEV_TX_OK; |
134 | } | 133 | } |
135 | 134 | ||
135 | static int vcan_change_mtu(struct net_device *dev, int new_mtu) | ||
136 | { | ||
137 | /* Do not allow changing the MTU while running */ | ||
138 | if (dev->flags & IFF_UP) | ||
139 | return -EBUSY; | ||
140 | |||
141 | if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU) | ||
142 | return -EINVAL; | ||
143 | |||
144 | dev->mtu = new_mtu; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
136 | static const struct net_device_ops vcan_netdev_ops = { | 148 | static const struct net_device_ops vcan_netdev_ops = { |
137 | .ndo_start_xmit = vcan_tx, | 149 | .ndo_start_xmit = vcan_tx, |
150 | .ndo_change_mtu = vcan_change_mtu, | ||
138 | }; | 151 | }; |
139 | 152 | ||
140 | static void vcan_setup(struct net_device *dev) | 153 | static void vcan_setup(struct net_device *dev) |
141 | { | 154 | { |
142 | dev->type = ARPHRD_CAN; | 155 | dev->type = ARPHRD_CAN; |
143 | dev->mtu = sizeof(struct can_frame); | 156 | dev->mtu = CAN_MTU; |
144 | dev->hard_header_len = 0; | 157 | dev->hard_header_len = 0; |
145 | dev->addr_len = 0; | 158 | dev->addr_len = 0; |
146 | dev->tx_queue_len = 0; | 159 | dev->tx_queue_len = 0; |