diff options
Diffstat (limited to 'drivers/net/can/vcan.c')
| -rw-r--r-- | drivers/net/can/vcan.c | 42 | 
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index a30b8f480f6..4e94057ef5c 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -37,8 +37,6 @@   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   * DAMAGE.   * - * Send feedback to <socketcan-users@lists.berlios.de> - *   */  #include <linux/module.h> @@ -48,10 +46,11 @@  #include <linux/if_ether.h>  #include <linux/can.h>  #include <linux/can/dev.h> +#include <linux/can/skb.h>  #include <linux/slab.h>  #include <net/rtnetlink.h> -static __initdata const char banner[] = +static __initconst const char banner[] =  	KERN_INFO "vcan: Virtual CAN interface driver\n";  MODULE_DESCRIPTION("virtual CAN interface"); @@ -65,20 +64,19 @@ MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");   * See Documentation/networking/can.txt for details.   */ -static int echo; /* echo testing. Default: 0 (Off) */ +static bool echo; /* echo testing. Default: 0 (Off) */  module_param(echo, bool, S_IRUGO);  MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");  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;  	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->dev       = dev;  	skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -88,7 +86,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)  { -	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;  	int loop; @@ -96,7 +94,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)  		return NETDEV_TX_OK;  	stats->tx_packets++; -	stats->tx_bytes += cf->can_dlc; +	stats->tx_bytes += cfd->len;  	/* set flag whether this packet has to be looped back */  	loop = skb->pkt_type == PACKET_LOOPBACK; @@ -110,39 +108,51 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)  			 * CAN core already did the echo for us  			 */  			stats->rx_packets++; -			stats->rx_bytes += cf->can_dlc; +			stats->rx_bytes += cfd->len;  		} -		kfree_skb(skb); +		consume_skb(skb);  		return NETDEV_TX_OK;  	}  	/* perform standard echo handling for CAN network interfaces */  	if (loop) { -		struct sock *srcsk = skb->sk; -		skb = skb_share_check(skb, GFP_ATOMIC); +		skb = can_create_echo_skb(skb);  		if (!skb)  			return NETDEV_TX_OK;  		/* receive with packet counting */ -		skb->sk = srcsk;  		vcan_rx(skb, dev);  	} else {  		/* no looped packets => no counting */ -		kfree_skb(skb); +		consume_skb(skb);  	}  	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 = {  	.ndo_start_xmit = vcan_tx, +	.ndo_change_mtu = vcan_change_mtu,  };  static void vcan_setup(struct net_device *dev)  {  	dev->type		= ARPHRD_CAN; -	dev->mtu		= sizeof(struct can_frame); +	dev->mtu		= CAN_MTU;  	dev->hard_header_len	= 0;  	dev->addr_len		= 0;  	dev->tx_queue_len	= 0;  | 
