aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Hartkopp <socketcan@hartkopp.net>2016-03-21 15:18:21 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2016-05-09 05:07:28 -0400
commitbb208f144cf3f59d8f89a09a80efd04389718907 (patch)
treedbf6d52a61a76aafa28e907d6d419464aa3fba89
parentb6fd3aba6041922e115bd8e10539b8545f4120ac (diff)
can: fix handling of unmodifiable configuration options
As described in 'can: m_can: tag current CAN FD controllers as non-ISO' (6cfda7fbebe) it is possible to define fixed configuration options by setting the according bit in 'ctrlmode' and clear it in 'ctrlmode_supported'. This leads to the incovenience that the fixed configuration bits can not be passed by netlink even when they have the correct values (e.g. non-ISO, FD). This patch fixes that issue and not only allows fixed set bit values to be set again but now requires(!) to provide these fixed values at configuration time. A valid CAN FD configuration consists of a nominal/arbitration bittiming, a data bittiming and a control mode with CAN_CTRLMODE_FD set - which is now enforced by a new can_validate() function. This fix additionally removed the inconsistency that was prohibiting the support of 'CANFD-only' controller drivers, like the RCar CAN FD. For this reason a new helper can_set_static_ctrlmode() has been introduced to provide a proper interface to handle static enabled CAN controller options. Reported-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Reviewed-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com> Cc: <stable@vger.kernel.org> # >= 3.18 Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/dev.c56
-rw-r--r--drivers/net/can/m_can/m_can.c2
-rw-r--r--include/linux/can/dev.h22
3 files changed, 73 insertions, 7 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 141c2a42d7ed..910c12e2638e 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -696,11 +696,17 @@ int can_change_mtu(struct net_device *dev, int new_mtu)
696 /* allow change of MTU according to the CANFD ability of the device */ 696 /* allow change of MTU according to the CANFD ability of the device */
697 switch (new_mtu) { 697 switch (new_mtu) {
698 case CAN_MTU: 698 case CAN_MTU:
699 /* 'CANFD-only' controllers can not switch to CAN_MTU */
700 if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
701 return -EINVAL;
702
699 priv->ctrlmode &= ~CAN_CTRLMODE_FD; 703 priv->ctrlmode &= ~CAN_CTRLMODE_FD;
700 break; 704 break;
701 705
702 case CANFD_MTU: 706 case CANFD_MTU:
703 if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD)) 707 /* check for potential CANFD ability */
708 if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
709 !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
704 return -EINVAL; 710 return -EINVAL;
705 711
706 priv->ctrlmode |= CAN_CTRLMODE_FD; 712 priv->ctrlmode |= CAN_CTRLMODE_FD;
@@ -782,6 +788,35 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
782 = { .len = sizeof(struct can_bittiming_const) }, 788 = { .len = sizeof(struct can_bittiming_const) },
783}; 789};
784 790
791static int can_validate(struct nlattr *tb[], struct nlattr *data[])
792{
793 bool is_can_fd = false;
794
795 /* Make sure that valid CAN FD configurations always consist of
796 * - nominal/arbitration bittiming
797 * - data bittiming
798 * - control mode with CAN_CTRLMODE_FD set
799 */
800
801 if (data[IFLA_CAN_CTRLMODE]) {
802 struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
803
804 is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
805 }
806
807 if (is_can_fd) {
808 if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
809 return -EOPNOTSUPP;
810 }
811
812 if (data[IFLA_CAN_DATA_BITTIMING]) {
813 if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
814 return -EOPNOTSUPP;
815 }
816
817 return 0;
818}
819
785static int can_changelink(struct net_device *dev, 820static int can_changelink(struct net_device *dev,
786 struct nlattr *tb[], struct nlattr *data[]) 821 struct nlattr *tb[], struct nlattr *data[])
787{ 822{
@@ -813,19 +848,31 @@ static int can_changelink(struct net_device *dev,
813 848
814 if (data[IFLA_CAN_CTRLMODE]) { 849 if (data[IFLA_CAN_CTRLMODE]) {
815 struct can_ctrlmode *cm; 850 struct can_ctrlmode *cm;
851 u32 ctrlstatic;
852 u32 maskedflags;
816 853
817 /* Do not allow changing controller mode while running */ 854 /* Do not allow changing controller mode while running */
818 if (dev->flags & IFF_UP) 855 if (dev->flags & IFF_UP)
819 return -EBUSY; 856 return -EBUSY;
820 cm = nla_data(data[IFLA_CAN_CTRLMODE]); 857 cm = nla_data(data[IFLA_CAN_CTRLMODE]);
858 ctrlstatic = priv->ctrlmode_static;
859 maskedflags = cm->flags & cm->mask;
860
861 /* check whether provided bits are allowed to be passed */
862 if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
863 return -EOPNOTSUPP;
864
865 /* do not check for static fd-non-iso if 'fd' is disabled */
866 if (!(maskedflags & CAN_CTRLMODE_FD))
867 ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
821 868
822 /* check whether changed bits are allowed to be modified */ 869 /* make sure static options are provided by configuration */
823 if (cm->mask & ~priv->ctrlmode_supported) 870 if ((maskedflags & ctrlstatic) != ctrlstatic)
824 return -EOPNOTSUPP; 871 return -EOPNOTSUPP;
825 872
826 /* clear bits to be modified and copy the flag values */ 873 /* clear bits to be modified and copy the flag values */
827 priv->ctrlmode &= ~cm->mask; 874 priv->ctrlmode &= ~cm->mask;
828 priv->ctrlmode |= (cm->flags & cm->mask); 875 priv->ctrlmode |= maskedflags;
829 876
830 /* CAN_CTRLMODE_FD can only be set when driver supports FD */ 877 /* CAN_CTRLMODE_FD can only be set when driver supports FD */
831 if (priv->ctrlmode & CAN_CTRLMODE_FD) 878 if (priv->ctrlmode & CAN_CTRLMODE_FD)
@@ -966,6 +1013,7 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
966 .maxtype = IFLA_CAN_MAX, 1013 .maxtype = IFLA_CAN_MAX,
967 .policy = can_policy, 1014 .policy = can_policy,
968 .setup = can_setup, 1015 .setup = can_setup,
1016 .validate = can_validate,
969 .newlink = can_newlink, 1017 .newlink = can_newlink,
970 .changelink = can_changelink, 1018 .changelink = can_changelink,
971 .get_size = can_get_size, 1019 .get_size = can_get_size,
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 39cf911f7a1e..195f15edb32e 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -955,7 +955,7 @@ static struct net_device *alloc_m_can_dev(void)
955 priv->can.do_get_berr_counter = m_can_get_berr_counter; 955 priv->can.do_get_berr_counter = m_can_get_berr_counter;
956 956
957 /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */ 957 /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */
958 priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO; 958 can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
959 959
960 /* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */ 960 /* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */
961 priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 961 priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 735f9f8c4e43..5261751f6bd4 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -40,8 +40,11 @@ struct can_priv {
40 struct can_clock clock; 40 struct can_clock clock;
41 41
42 enum can_state state; 42 enum can_state state;
43 u32 ctrlmode; 43
44 u32 ctrlmode_supported; 44 /* CAN controller features - see include/uapi/linux/can/netlink.h */
45 u32 ctrlmode; /* current options setting */
46 u32 ctrlmode_supported; /* options that can be modified by netlink */
47 u32 ctrlmode_static; /* static enabled options for driver/hardware */
45 48
46 int restart_ms; 49 int restart_ms;
47 struct timer_list restart_timer; 50 struct timer_list restart_timer;
@@ -108,6 +111,21 @@ static inline bool can_is_canfd_skb(const struct sk_buff *skb)
108 return skb->len == CANFD_MTU; 111 return skb->len == CANFD_MTU;
109} 112}
110 113
114/* helper to define static CAN controller features at device creation time */
115static inline void can_set_static_ctrlmode(struct net_device *dev,
116 u32 static_mode)
117{
118 struct can_priv *priv = netdev_priv(dev);
119
120 /* alloc_candev() succeeded => netdev_priv() is valid at this point */
121 priv->ctrlmode = static_mode;
122 priv->ctrlmode_static = static_mode;
123
124 /* override MTU which was set by default in can_setup()? */
125 if (static_mode & CAN_CTRLMODE_FD)
126 dev->mtu = CANFD_MTU;
127}
128
111/* get data length from can_dlc with sanitized can_dlc */ 129/* get data length from can_dlc with sanitized can_dlc */
112u8 can_dlc2len(u8 can_dlc); 130u8 can_dlc2len(u8 can_dlc);
113 131