Skip to content

Commit 6c1f514

Browse files
Merge patch series "can: raw: better approach to instantly reject unsupported CAN frames"
Oliver Hartkopp <socketcan@hartkopp.net> says: This series reverts commit 1a620a7 ("can: raw: instantly reject unsupported CAN frames"). and its follow-up fixes for the introduced dependency issues. commit 1a620a7 ("can: raw: instantly reject unsupported CAN frames") commit cb2dc6d ("can: Kconfig: select CAN driver infrastructure by default") commit 6abd457 ("can: fix build dependency") commit 5a5aff6 ("can: fix build dependency") The reverted patch was accessing CAN device internal data structures from the network layer because it needs to know about the CAN protocol capabilities of the CAN devices. This data access caused build problems between the CAN network and the CAN driver layer which introduced unwanted Kconfig dependencies and fixes. The patches 2 & 3 implement a better approach which makes use of the CAN specific ml_priv data which is accessible from both sides. With this change the CAN network layer can check the required features and the decoupling of the driver layer and network layer is restored. Link: https://patch.msgid.link/20260109144135.8495-1-socketcan@hartkopp.net [mkl: give series a more descriptive name] [mkl: properly format reverted patch commitish] Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2 parents 3879cff + faba586 commit 6c1f514

10 files changed

Lines changed: 102 additions & 53 deletions

File tree

drivers/net/can/Kconfig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22

33
menuconfig CAN_DEV
4-
bool "CAN Device Drivers"
4+
tristate "CAN Device Drivers"
55
default y
66
depends on CAN
77
help
@@ -17,7 +17,10 @@ menuconfig CAN_DEV
1717
virtual ones. If you own such devices or plan to use the virtual CAN
1818
interfaces to develop applications, say Y here.
1919

20-
if CAN_DEV && CAN
20+
To compile as a module, choose M here: the module will be called
21+
can-dev.
22+
23+
if CAN_DEV
2124

2225
config CAN_VCAN
2326
tristate "Virtual Local CAN Interface (vcan)"

drivers/net/can/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
77
obj-$(CONFIG_CAN_VXCAN) += vxcan.o
88
obj-$(CONFIG_CAN_SLCAN) += slcan/
99

10-
obj-$(CONFIG_CAN_DEV) += dev/
10+
obj-y += dev/
1111
obj-y += esd/
1212
obj-y += rcar/
1313
obj-y += rockchip/

drivers/net/can/dev/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0
22

3-
obj-$(CONFIG_CAN) += can-dev.o
3+
obj-$(CONFIG_CAN_DEV) += can-dev.o
4+
5+
can-dev-y += skb.o
46

5-
can-dev-$(CONFIG_CAN_DEV) += skb.o
67
can-dev-$(CONFIG_CAN_CALC_BITTIMING) += calc_bittiming.o
78
can-dev-$(CONFIG_CAN_NETLINK) += bittiming.o
89
can-dev-$(CONFIG_CAN_NETLINK) += dev.o

drivers/net/can/dev/dev.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,32 @@ void can_set_default_mtu(struct net_device *dev)
375375
}
376376
}
377377

378+
void can_set_cap_info(struct net_device *dev)
379+
{
380+
struct can_priv *priv = netdev_priv(dev);
381+
u32 can_cap;
382+
383+
if (can_dev_in_xl_only_mode(priv)) {
384+
/* XL only mode => no CC/FD capability */
385+
can_cap = CAN_CAP_XL;
386+
} else {
387+
/* mixed mode => CC + FD/XL capability */
388+
can_cap = CAN_CAP_CC;
389+
390+
if (priv->ctrlmode & CAN_CTRLMODE_FD)
391+
can_cap |= CAN_CAP_FD;
392+
393+
if (priv->ctrlmode & CAN_CTRLMODE_XL)
394+
can_cap |= CAN_CAP_XL;
395+
}
396+
397+
if (priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY |
398+
CAN_CTRLMODE_RESTRICTED))
399+
can_cap |= CAN_CAP_RO;
400+
401+
can_set_cap(dev, can_cap);
402+
}
403+
378404
/* helper to define static CAN controller features at device creation time */
379405
int can_set_static_ctrlmode(struct net_device *dev, u32 static_mode)
380406
{
@@ -390,6 +416,7 @@ int can_set_static_ctrlmode(struct net_device *dev, u32 static_mode)
390416

391417
/* override MTU which was set by default in can_setup()? */
392418
can_set_default_mtu(dev);
419+
can_set_cap_info(dev);
393420

394421
return 0;
395422
}

drivers/net/can/dev/netlink.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ static int can_ctrlmode_changelink(struct net_device *dev,
377377
}
378378

379379
can_set_default_mtu(dev);
380+
can_set_cap_info(dev);
380381

381382
return 0;
382383
}

drivers/net/can/vcan.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
130130
return NETDEV_TX_OK;
131131
}
132132

133+
static void vcan_set_cap_info(struct net_device *dev)
134+
{
135+
u32 can_cap = CAN_CAP_CC;
136+
137+
if (dev->mtu > CAN_MTU)
138+
can_cap |= CAN_CAP_FD;
139+
140+
if (dev->mtu >= CANXL_MIN_MTU)
141+
can_cap |= CAN_CAP_XL;
142+
143+
can_set_cap(dev, can_cap);
144+
}
145+
133146
static int vcan_change_mtu(struct net_device *dev, int new_mtu)
134147
{
135148
/* Do not allow changing the MTU while running */
@@ -141,6 +154,7 @@ static int vcan_change_mtu(struct net_device *dev, int new_mtu)
141154
return -EINVAL;
142155

143156
WRITE_ONCE(dev->mtu, new_mtu);
157+
vcan_set_cap_info(dev);
144158
return 0;
145159
}
146160

@@ -162,6 +176,7 @@ static void vcan_setup(struct net_device *dev)
162176
dev->tx_queue_len = 0;
163177
dev->flags = IFF_NOARP;
164178
can_set_ml_priv(dev, netdev_priv(dev));
179+
vcan_set_cap_info(dev);
165180

166181
/* set flags according to driver capabilities */
167182
if (echo)

drivers/net/can/vxcan.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,19 @@ static int vxcan_get_iflink(const struct net_device *dev)
125125
return iflink;
126126
}
127127

128+
static void vxcan_set_cap_info(struct net_device *dev)
129+
{
130+
u32 can_cap = CAN_CAP_CC;
131+
132+
if (dev->mtu > CAN_MTU)
133+
can_cap |= CAN_CAP_FD;
134+
135+
if (dev->mtu >= CANXL_MIN_MTU)
136+
can_cap |= CAN_CAP_XL;
137+
138+
can_set_cap(dev, can_cap);
139+
}
140+
128141
static int vxcan_change_mtu(struct net_device *dev, int new_mtu)
129142
{
130143
/* Do not allow changing the MTU while running */
@@ -136,6 +149,7 @@ static int vxcan_change_mtu(struct net_device *dev, int new_mtu)
136149
return -EINVAL;
137150

138151
WRITE_ONCE(dev->mtu, new_mtu);
152+
vxcan_set_cap_info(dev);
139153
return 0;
140154
}
141155

@@ -167,6 +181,7 @@ static void vxcan_setup(struct net_device *dev)
167181

168182
can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
169183
can_set_ml_priv(dev, can_ml);
184+
vxcan_set_cap_info(dev);
170185
}
171186

172187
/* forward declaration for rtnl_create_link() */

include/linux/can/can-ml.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
#include <linux/list.h>
4747
#include <linux/netdevice.h>
4848

49+
/* exposed CAN device capabilities for network layer */
50+
#define CAN_CAP_CC BIT(0) /* CAN CC aka Classical CAN */
51+
#define CAN_CAP_FD BIT(1) /* CAN FD */
52+
#define CAN_CAP_XL BIT(2) /* CAN XL */
53+
#define CAN_CAP_RO BIT(3) /* read-only mode (LISTEN/RESTRICTED) */
54+
4955
#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
5056
#define CAN_EFF_RCV_HASH_BITS 10
5157
#define CAN_EFF_RCV_ARRAY_SZ (1 << CAN_EFF_RCV_HASH_BITS)
@@ -64,6 +70,7 @@ struct can_ml_priv {
6470
#ifdef CAN_J1939
6571
struct j1939_priv *j1939_priv;
6672
#endif
73+
u32 can_cap;
6774
};
6875

6976
static inline struct can_ml_priv *can_get_ml_priv(struct net_device *dev)
@@ -77,4 +84,21 @@ static inline void can_set_ml_priv(struct net_device *dev,
7784
netdev_set_ml_priv(dev, ml_priv, ML_PRIV_CAN);
7885
}
7986

87+
static inline bool can_cap_enabled(struct net_device *dev, u32 cap)
88+
{
89+
struct can_ml_priv *can_ml = can_get_ml_priv(dev);
90+
91+
if (!can_ml)
92+
return false;
93+
94+
return (can_ml->can_cap & cap);
95+
}
96+
97+
static inline void can_set_cap(struct net_device *dev, u32 cap)
98+
{
99+
struct can_ml_priv *can_ml = can_get_ml_priv(dev);
100+
101+
can_ml->can_cap = cap;
102+
}
103+
80104
#endif /* CAN_ML_H */

include/linux/can/dev.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,12 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
111111
void free_candev(struct net_device *dev);
112112

113113
/* a candev safe wrapper around netdev_priv */
114-
#if IS_ENABLED(CONFIG_CAN_NETLINK)
115114
struct can_priv *safe_candev_priv(struct net_device *dev);
116-
#else
117-
static inline struct can_priv *safe_candev_priv(struct net_device *dev)
118-
{
119-
return NULL;
120-
}
121-
#endif
122115

123116
int open_candev(struct net_device *dev);
124117
void close_candev(struct net_device *dev);
125118
void can_set_default_mtu(struct net_device *dev);
119+
void can_set_cap_info(struct net_device *dev);
126120
int __must_check can_set_static_ctrlmode(struct net_device *dev,
127121
u32 static_mode);
128122
int can_hwtstamp_get(struct net_device *netdev,

net/can/raw.c

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
#include <linux/if_arp.h>
5050
#include <linux/skbuff.h>
5151
#include <linux/can.h>
52+
#include <linux/can/can-ml.h>
5253
#include <linux/can/core.h>
53-
#include <linux/can/dev.h> /* for can_is_canxl_dev_mtu() */
5454
#include <linux/can/skb.h>
5555
#include <linux/can/raw.h>
5656
#include <net/sock.h>
@@ -892,58 +892,21 @@ static void raw_put_canxl_vcid(struct raw_sock *ro, struct sk_buff *skb)
892892
}
893893
}
894894

895-
static inline bool raw_dev_cc_enabled(struct net_device *dev,
896-
struct can_priv *priv)
897-
{
898-
/* The CANXL-only mode disables error-signalling on the CAN bus
899-
* which is needed to send CAN CC/FD frames
900-
*/
901-
if (priv)
902-
return !can_dev_in_xl_only_mode(priv);
903-
904-
/* virtual CAN interfaces always support CAN CC */
905-
return true;
906-
}
907-
908-
static inline bool raw_dev_fd_enabled(struct net_device *dev,
909-
struct can_priv *priv)
910-
{
911-
/* check FD ctrlmode on real CAN interfaces */
912-
if (priv)
913-
return (priv->ctrlmode & CAN_CTRLMODE_FD);
914-
915-
/* check MTU for virtual CAN FD interfaces */
916-
return (READ_ONCE(dev->mtu) >= CANFD_MTU);
917-
}
918-
919-
static inline bool raw_dev_xl_enabled(struct net_device *dev,
920-
struct can_priv *priv)
921-
{
922-
/* check XL ctrlmode on real CAN interfaces */
923-
if (priv)
924-
return (priv->ctrlmode & CAN_CTRLMODE_XL);
925-
926-
/* check MTU for virtual CAN XL interfaces */
927-
return can_is_canxl_dev_mtu(READ_ONCE(dev->mtu));
928-
}
929-
930895
static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb,
931896
struct net_device *dev)
932897
{
933-
struct can_priv *priv = safe_candev_priv(dev);
934-
935898
/* Classical CAN */
936-
if (can_is_can_skb(skb) && raw_dev_cc_enabled(dev, priv))
899+
if (can_is_can_skb(skb) && can_cap_enabled(dev, CAN_CAP_CC))
937900
return CAN_MTU;
938901

939902
/* CAN FD */
940903
if (ro->fd_frames && can_is_canfd_skb(skb) &&
941-
raw_dev_fd_enabled(dev, priv))
904+
can_cap_enabled(dev, CAN_CAP_FD))
942905
return CANFD_MTU;
943906

944907
/* CAN XL */
945908
if (ro->xl_frames && can_is_canxl_skb(skb) &&
946-
raw_dev_xl_enabled(dev, priv))
909+
can_cap_enabled(dev, CAN_CAP_XL))
947910
return CANXL_MTU;
948911

949912
return 0;
@@ -982,6 +945,12 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
982945
if (!dev)
983946
return -ENXIO;
984947

948+
/* no sending on a CAN device in read-only mode */
949+
if (can_cap_enabled(dev, CAN_CAP_RO)) {
950+
err = -EACCES;
951+
goto put_dev;
952+
}
953+
985954
skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
986955
msg->msg_flags & MSG_DONTWAIT, &err);
987956
if (!skb)

0 commit comments

Comments
 (0)