]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.6.1/can-fix-handling-of-unmodifiable-configuration-options.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.6.1 / can-fix-handling-of-unmodifiable-configuration-options.patch
1 From bb208f144cf3f59d8f89a09a80efd04389718907 Mon Sep 17 00:00:00 2001
2 From: Oliver Hartkopp <socketcan@hartkopp.net>
3 Date: Mon, 21 Mar 2016 20:18:21 +0100
4 Subject: can: fix handling of unmodifiable configuration options
5
6 From: Oliver Hartkopp <socketcan@hartkopp.net>
7
8 commit bb208f144cf3f59d8f89a09a80efd04389718907 upstream.
9
10 As described in 'can: m_can: tag current CAN FD controllers as non-ISO'
11 (6cfda7fbebe) it is possible to define fixed configuration options by
12 setting the according bit in 'ctrlmode' and clear it in 'ctrlmode_supported'.
13 This leads to the incovenience that the fixed configuration bits can not be
14 passed by netlink even when they have the correct values (e.g. non-ISO, FD).
15
16 This patch fixes that issue and not only allows fixed set bit values to be set
17 again but now requires(!) to provide these fixed values at configuration time.
18 A valid CAN FD configuration consists of a nominal/arbitration bittiming, a
19 data bittiming and a control mode with CAN_CTRLMODE_FD set - which is now
20 enforced by a new can_validate() function. This fix additionally removed the
21 inconsistency that was prohibiting the support of 'CANFD-only' controller
22 drivers, like the RCar CAN FD.
23
24 For this reason a new helper can_set_static_ctrlmode() has been introduced to
25 provide a proper interface to handle static enabled CAN controller options.
26
27 Reported-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
28 Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
29 Reviewed-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
30 Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32
33 ---
34 drivers/net/can/dev.c | 56 +++++++++++++++++++++++++++++++++++++++---
35 drivers/net/can/m_can/m_can.c | 2 -
36 include/linux/can/dev.h | 22 +++++++++++++++-
37 3 files changed, 73 insertions(+), 7 deletions(-)
38
39 --- a/drivers/net/can/dev.c
40 +++ b/drivers/net/can/dev.c
41 @@ -696,11 +696,17 @@ int can_change_mtu(struct net_device *de
42 /* allow change of MTU according to the CANFD ability of the device */
43 switch (new_mtu) {
44 case CAN_MTU:
45 + /* 'CANFD-only' controllers can not switch to CAN_MTU */
46 + if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
47 + return -EINVAL;
48 +
49 priv->ctrlmode &= ~CAN_CTRLMODE_FD;
50 break;
51
52 case CANFD_MTU:
53 - if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD))
54 + /* check for potential CANFD ability */
55 + if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
56 + !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
57 return -EINVAL;
58
59 priv->ctrlmode |= CAN_CTRLMODE_FD;
60 @@ -782,6 +788,35 @@ static const struct nla_policy can_polic
61 = { .len = sizeof(struct can_bittiming_const) },
62 };
63
64 +static int can_validate(struct nlattr *tb[], struct nlattr *data[])
65 +{
66 + bool is_can_fd = false;
67 +
68 + /* Make sure that valid CAN FD configurations always consist of
69 + * - nominal/arbitration bittiming
70 + * - data bittiming
71 + * - control mode with CAN_CTRLMODE_FD set
72 + */
73 +
74 + if (data[IFLA_CAN_CTRLMODE]) {
75 + struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
76 +
77 + is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
78 + }
79 +
80 + if (is_can_fd) {
81 + if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
82 + return -EOPNOTSUPP;
83 + }
84 +
85 + if (data[IFLA_CAN_DATA_BITTIMING]) {
86 + if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
87 + return -EOPNOTSUPP;
88 + }
89 +
90 + return 0;
91 +}
92 +
93 static int can_changelink(struct net_device *dev,
94 struct nlattr *tb[], struct nlattr *data[])
95 {
96 @@ -813,19 +848,31 @@ static int can_changelink(struct net_dev
97
98 if (data[IFLA_CAN_CTRLMODE]) {
99 struct can_ctrlmode *cm;
100 + u32 ctrlstatic;
101 + u32 maskedflags;
102
103 /* Do not allow changing controller mode while running */
104 if (dev->flags & IFF_UP)
105 return -EBUSY;
106 cm = nla_data(data[IFLA_CAN_CTRLMODE]);
107 + ctrlstatic = priv->ctrlmode_static;
108 + maskedflags = cm->flags & cm->mask;
109 +
110 + /* check whether provided bits are allowed to be passed */
111 + if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
112 + return -EOPNOTSUPP;
113 +
114 + /* do not check for static fd-non-iso if 'fd' is disabled */
115 + if (!(maskedflags & CAN_CTRLMODE_FD))
116 + ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
117
118 - /* check whether changed bits are allowed to be modified */
119 - if (cm->mask & ~priv->ctrlmode_supported)
120 + /* make sure static options are provided by configuration */
121 + if ((maskedflags & ctrlstatic) != ctrlstatic)
122 return -EOPNOTSUPP;
123
124 /* clear bits to be modified and copy the flag values */
125 priv->ctrlmode &= ~cm->mask;
126 - priv->ctrlmode |= (cm->flags & cm->mask);
127 + priv->ctrlmode |= maskedflags;
128
129 /* CAN_CTRLMODE_FD can only be set when driver supports FD */
130 if (priv->ctrlmode & CAN_CTRLMODE_FD)
131 @@ -966,6 +1013,7 @@ static struct rtnl_link_ops can_link_ops
132 .maxtype = IFLA_CAN_MAX,
133 .policy = can_policy,
134 .setup = can_setup,
135 + .validate = can_validate,
136 .newlink = can_newlink,
137 .changelink = can_changelink,
138 .get_size = can_get_size,
139 --- a/drivers/net/can/m_can/m_can.c
140 +++ b/drivers/net/can/m_can/m_can.c
141 @@ -955,7 +955,7 @@ static struct net_device *alloc_m_can_de
142 priv->can.do_get_berr_counter = m_can_get_berr_counter;
143
144 /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */
145 - priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO;
146 + can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
147
148 /* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */
149 priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
150 --- a/include/linux/can/dev.h
151 +++ b/include/linux/can/dev.h
152 @@ -40,8 +40,11 @@ struct can_priv {
153 struct can_clock clock;
154
155 enum can_state state;
156 - u32 ctrlmode;
157 - u32 ctrlmode_supported;
158 +
159 + /* CAN controller features - see include/uapi/linux/can/netlink.h */
160 + u32 ctrlmode; /* current options setting */
161 + u32 ctrlmode_supported; /* options that can be modified by netlink */
162 + u32 ctrlmode_static; /* static enabled options for driver/hardware */
163
164 int restart_ms;
165 struct timer_list restart_timer;
166 @@ -108,6 +111,21 @@ static inline bool can_is_canfd_skb(cons
167 return skb->len == CANFD_MTU;
168 }
169
170 +/* helper to define static CAN controller features at device creation time */
171 +static inline void can_set_static_ctrlmode(struct net_device *dev,
172 + u32 static_mode)
173 +{
174 + struct can_priv *priv = netdev_priv(dev);
175 +
176 + /* alloc_candev() succeeded => netdev_priv() is valid at this point */
177 + priv->ctrlmode = static_mode;
178 + priv->ctrlmode_static = static_mode;
179 +
180 + /* override MTU which was set by default in can_setup()? */
181 + if (static_mode & CAN_CTRLMODE_FD)
182 + dev->mtu = CANFD_MTU;
183 +}
184 +
185 /* get data length from can_dlc with sanitized can_dlc */
186 u8 can_dlc2len(u8 can_dlc);
187