can: allow to change the device mtu for CAN FD capable devices
authorOliver Hartkopp <socketcan@hartkopp.net>
Fri, 28 Feb 2014 15:36:24 +0000 (16:36 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 7 Mar 2014 08:18:23 +0000 (09:18 +0100)
The configuration for CAN FD depends on CAN_CTRLMODE_FD enabled in the driver
specific ctrlmode_supported capabilities.

The configuration can be done either with the 'fd { on | off }' option in the
'ip' tool from iproute2 or by setting the CAN netdevice MTU to CAN_MTU (16) or
to CANFD_MTU (72).

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/dev.c
include/linux/can/dev.h
include/uapi/linux/can/netlink.h

index 8ebe112458c4669f615d923e73d0280e38ba3477..4e20d82b799e4e7b35d8b524af4ed748963faba9 100644 (file)
@@ -594,6 +594,39 @@ void free_candev(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(free_candev);
 
+/*
+ * changing MTU and control mode for CAN/CANFD devices
+ */
+int can_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct can_priv *priv = netdev_priv(dev);
+
+       /* Do not allow changing the MTU while running */
+       if (dev->flags & IFF_UP)
+               return -EBUSY;
+
+       /* allow change of MTU according to the CANFD ability of the device */
+       switch (new_mtu) {
+       case CAN_MTU:
+               priv->ctrlmode &= ~CAN_CTRLMODE_FD;
+               break;
+
+       case CANFD_MTU:
+               if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD))
+                       return -EINVAL;
+
+               priv->ctrlmode |= CAN_CTRLMODE_FD;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(can_change_mtu);
+
 /*
  * Common open function when the device gets opened.
  *
@@ -693,6 +726,12 @@ static int can_changelink(struct net_device *dev,
                        return -EOPNOTSUPP;
                priv->ctrlmode &= ~cm->mask;
                priv->ctrlmode |= cm->flags;
+
+               /* CAN_CTRLMODE_FD can only be set when driver supports FD */
+               if (priv->ctrlmode & CAN_CTRLMODE_FD)
+                       dev->mtu = CANFD_MTU;
+               else
+                       dev->mtu = CAN_MTU;
        }
 
        if (data[IFLA_CAN_RESTART_MS]) {
index 8adaee96f29285c2b301b3494a94bc5d5dfc1f2b..3ce5e526525f852f37ea242700363036c85068ca 100644 (file)
@@ -113,6 +113,7 @@ struct can_priv *safe_candev_priv(struct net_device *dev);
 
 int open_candev(struct net_device *dev);
 void close_candev(struct net_device *dev);
+int can_change_mtu(struct net_device *dev, int new_mtu);
 
 int register_candev(struct net_device *dev);
 void unregister_candev(struct net_device *dev);
index b41933d6bdcd2de7eb0847e5ccdf387b52c4e069..7e2e1863db16e02fa15e1edc109adefda8236ba7 100644 (file)
@@ -96,6 +96,7 @@ struct can_ctrlmode {
 #define CAN_CTRLMODE_3_SAMPLES         0x04    /* Triple sampling mode */
 #define CAN_CTRLMODE_ONE_SHOT          0x08    /* One-Shot mode */
 #define CAN_CTRLMODE_BERR_REPORTING    0x10    /* Bus-error reporting */
+#define CAN_CTRLMODE_FD                        0x20    /* CAN FD mode */
 
 /*
  * CAN device statistics