Merge tag 'linux-can-next-for-6.17-20250610' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
Marc Kleine-Budde says: ==================== pull-request: can-next 2025-06-10 The first 4 patches are by Vincent Mailhol and prepare the CAN netlink interface for the introduction of CAN XL configuration. Geert Uytterhoeven's patch updates the CAN networking documentation. The last 2 patched are by Davide Caratti and introduce skb drop reasons in the receive path of several CAN protocols. * tag 'linux-can-next-for-6.17-20250610' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: can: add drop reasons in CAN protocols receive path can: add drop reasons in the receive path of AF_CAN documentation: networking: can: Document alloc_candev_mqs() can: netlink: can_changelink(): rename tdc_mask into fd_tdc_flag_provided can: bittiming: rename can_tdc_is_enabled() into can_fd_tdc_is_enabled() can: bittiming: rename CAN_CTRLMODE_TDC_MASK into CAN_CTRLMODE_FD_TDC_MASK can: netlink: replace tabulation by space in assignment ==================== Link: https://patch.msgid.link/20250610094933.1593081-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -1104,15 +1104,12 @@ for writing CAN network device driver are described below:
|
||||
General Settings
|
||||
----------------
|
||||
|
||||
CAN network device drivers can use alloc_candev_mqs() and friends instead of
|
||||
alloc_netdev_mqs(), to automatically take care of CAN-specific setup:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
dev->type = ARPHRD_CAN; /* the netdevice hardware type */
|
||||
dev->flags = IFF_NOARP; /* CAN has no arp */
|
||||
|
||||
dev->mtu = CAN_MTU; /* sizeof(struct can_frame) -> Classical CAN interface */
|
||||
|
||||
or alternative, when the controller supports CAN with flexible data rate:
|
||||
dev->mtu = CANFD_MTU; /* sizeof(struct canfd_frame) -> CAN FD interface */
|
||||
dev = alloc_candev_mqs(...);
|
||||
|
||||
The struct can_frame or struct canfd_frame is the payload of each socket
|
||||
buffer (skbuff) in the protocol family PF_CAN.
|
||||
|
||||
@@ -179,7 +179,7 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
||||
if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO))
|
||||
return;
|
||||
|
||||
*ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
|
||||
*ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
|
||||
|
||||
/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
|
||||
* delay compensation" (TDC) is only applicable if data BRP is
|
||||
|
||||
@@ -18,7 +18,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
|
||||
[IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) },
|
||||
[IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
|
||||
[IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) },
|
||||
[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
|
||||
[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
|
||||
[IFLA_CAN_TERMINATION] = { .type = NLA_U16 },
|
||||
[IFLA_CAN_TDC] = { .type = NLA_NESTED },
|
||||
[IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED },
|
||||
@@ -67,12 +67,12 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
|
||||
|
||||
if (data[IFLA_CAN_CTRLMODE]) {
|
||||
struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
||||
u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK;
|
||||
u32 tdc_flags = cm->flags & CAN_CTRLMODE_FD_TDC_MASK;
|
||||
|
||||
is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
|
||||
|
||||
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
|
||||
if (tdc_flags == CAN_CTRLMODE_TDC_MASK)
|
||||
if (tdc_flags == CAN_CTRLMODE_FD_TDC_MASK)
|
||||
return -EOPNOTSUPP;
|
||||
/* If one of the CAN_CTRLMODE_TDC_* flag is set then
|
||||
* TDC must be set and vice-versa
|
||||
@@ -144,7 +144,7 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
|
||||
const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
|
||||
int err;
|
||||
|
||||
if (!tdc_const || !can_tdc_is_enabled(priv))
|
||||
if (!tdc_const || !can_fd_tdc_is_enabled(priv))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla,
|
||||
@@ -189,7 +189,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
u32 tdc_mask = 0;
|
||||
bool fd_tdc_flag_provided = false;
|
||||
int err;
|
||||
|
||||
/* We need synchronization with dev->stop() */
|
||||
@@ -230,16 +230,16 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
dev->mtu = CAN_MTU;
|
||||
memset(&priv->fd.data_bittiming, 0,
|
||||
sizeof(priv->fd.data_bittiming));
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
|
||||
memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
|
||||
}
|
||||
|
||||
tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK;
|
||||
fd_tdc_flag_provided = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
|
||||
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually
|
||||
* exclusive: make sure to turn the other one off
|
||||
*/
|
||||
if (tdc_mask)
|
||||
priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK;
|
||||
if (fd_tdc_flag_provided)
|
||||
priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_FD_TDC_MASK;
|
||||
}
|
||||
|
||||
if (data[IFLA_CAN_BITTIMING]) {
|
||||
@@ -339,10 +339,10 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
|
||||
extack);
|
||||
if (err) {
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
|
||||
return err;
|
||||
}
|
||||
} else if (!tdc_mask) {
|
||||
} else if (!fd_tdc_flag_provided) {
|
||||
/* Neither of TDC parameters nor TDC flags are
|
||||
* provided: do calculation
|
||||
*/
|
||||
@@ -409,7 +409,7 @@ static size_t can_tdc_get_size(const struct net_device *dev)
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MAX */
|
||||
}
|
||||
|
||||
if (can_tdc_is_enabled(priv)) {
|
||||
if (can_fd_tdc_is_enabled(priv)) {
|
||||
if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
|
||||
priv->fd.do_get_auto_tdcv)
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */
|
||||
@@ -490,7 +490,7 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
||||
nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MAX, tdc_const->tdcf_max)))
|
||||
goto err_cancel;
|
||||
|
||||
if (can_tdc_is_enabled(priv)) {
|
||||
if (can_fd_tdc_is_enabled(priv)) {
|
||||
u32 tdcv;
|
||||
int err = -EINVAL;
|
||||
|
||||
|
||||
@@ -429,7 +429,7 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv)
|
||||
es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,
|
||||
&priv->can.fd.data_bittiming);
|
||||
|
||||
if (can_tdc_is_enabled(&priv->can)) {
|
||||
if (can_fd_tdc_is_enabled(&priv->can)) {
|
||||
tx_conf_msg.tdc_enabled = 1;
|
||||
tx_conf_msg.tdco = cpu_to_le16(priv->can.fd.tdc.tdco);
|
||||
tx_conf_msg.tdcf = cpu_to_le16(priv->can.fd.tdc.tdcf);
|
||||
|
||||
@@ -515,7 +515,7 @@ static int xcan_set_bittiming(struct net_device *ndev)
|
||||
priv->devtype.cantype == XAXI_CANFD_2_0) {
|
||||
/* Setting Baud Rate prescaler value in F_BRPR Register */
|
||||
btr0 = dbt->brp - 1;
|
||||
if (can_tdc_is_enabled(&priv->can)) {
|
||||
if (can_fd_tdc_is_enabled(&priv->can)) {
|
||||
if (priv->devtype.cantype == XAXI_CANFD)
|
||||
btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
|
||||
XCAN_BRPR_TDC_ENABLE;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#define CAN_BITRATE_UNSET 0
|
||||
#define CAN_BITRATE_UNKNOWN (-1U)
|
||||
|
||||
#define CAN_CTRLMODE_TDC_MASK \
|
||||
#define CAN_CTRLMODE_FD_TDC_MASK \
|
||||
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
|
||||
|
||||
/*
|
||||
|
||||
@@ -91,9 +91,9 @@ struct can_priv {
|
||||
struct can_berr_counter *bec);
|
||||
};
|
||||
|
||||
static inline bool can_tdc_is_enabled(const struct can_priv *priv)
|
||||
static inline bool can_fd_tdc_is_enabled(const struct can_priv *priv)
|
||||
{
|
||||
return !!(priv->ctrlmode & CAN_CTRLMODE_TDC_MASK);
|
||||
return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -121,6 +121,9 @@
|
||||
FN(ARP_PVLAN_DISABLE) \
|
||||
FN(MAC_IEEE_MAC_CONTROL) \
|
||||
FN(BRIDGE_INGRESS_STP_STATE) \
|
||||
FN(CAN_RX_INVALID_FRAME) \
|
||||
FN(CANFD_RX_INVALID_FRAME) \
|
||||
FN(CANXL_RX_INVALID_FRAME) \
|
||||
FNe(MAX)
|
||||
|
||||
/**
|
||||
@@ -573,6 +576,21 @@ enum skb_drop_reason {
|
||||
* ingress bridge port does not allow frames to be forwarded.
|
||||
*/
|
||||
SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE,
|
||||
/**
|
||||
* @SKB_DROP_REASON_CAN_RX_INVALID_FRAME: received
|
||||
* non conform CAN frame (or device is unable to receive CAN frames)
|
||||
*/
|
||||
SKB_DROP_REASON_CAN_RX_INVALID_FRAME,
|
||||
/**
|
||||
* @SKB_DROP_REASON_CANFD_RX_INVALID_FRAME: received
|
||||
* non conform CAN-FD frame (or device is unable to receive CAN frames)
|
||||
*/
|
||||
SKB_DROP_REASON_CANFD_RX_INVALID_FRAME,
|
||||
/**
|
||||
* @SKB_DROP_REASON_CANXL_RX_INVALID_FRAME: received
|
||||
* non conform CAN-XL frame (or device is unable to receive CAN frames)
|
||||
*/
|
||||
SKB_DROP_REASON_CANXL_RX_INVALID_FRAME,
|
||||
/**
|
||||
* @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
|
||||
* shouldn't be used as a real 'reason' - only for tracing code gen
|
||||
|
||||
+3
-3
@@ -683,7 +683,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_CAN_RX_INVALID_FRAME);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_CANFD_RX_INVALID_FRAME);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
@@ -713,7 +713,7 @@ static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
|
||||
dev->type, skb->len);
|
||||
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_CANXL_RX_INVALID_FRAME);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -359,6 +359,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
|
||||
unsigned int datalen = head->nframes * op->cfsiz;
|
||||
int err;
|
||||
unsigned int *pflags;
|
||||
enum skb_drop_reason reason;
|
||||
|
||||
skb = alloc_skb(sizeof(*head) + datalen, gfp_any());
|
||||
if (!skb)
|
||||
@@ -413,11 +414,11 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
|
||||
addr->can_family = AF_CAN;
|
||||
addr->can_ifindex = op->rx_ifindex;
|
||||
|
||||
err = sock_queue_rcv_skb(sk, skb);
|
||||
err = sock_queue_rcv_skb_reason(sk, skb, &reason);
|
||||
if (err < 0) {
|
||||
struct bcm_sock *bo = bcm_sk(sk);
|
||||
|
||||
kfree_skb(skb);
|
||||
sk_skb_reason_drop(sk, skb, reason);
|
||||
/* don't care about overflows in this statistic */
|
||||
bo->dropped_usr_msgs++;
|
||||
}
|
||||
|
||||
+3
-2
@@ -278,6 +278,7 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
|
||||
static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)
|
||||
{
|
||||
struct sockaddr_can *addr = (struct sockaddr_can *)skb->cb;
|
||||
enum skb_drop_reason reason;
|
||||
|
||||
BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct sockaddr_can));
|
||||
|
||||
@@ -285,8 +286,8 @@ static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)
|
||||
addr->can_family = AF_CAN;
|
||||
addr->can_ifindex = skb->dev->ifindex;
|
||||
|
||||
if (sock_queue_rcv_skb(sk, skb) < 0)
|
||||
kfree_skb(skb);
|
||||
if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0)
|
||||
sk_skb_reason_drop(sk, skb, reason);
|
||||
}
|
||||
|
||||
static u8 padlen(u8 datalen)
|
||||
|
||||
@@ -311,6 +311,7 @@ static void j1939_sk_recv_one(struct j1939_sock *jsk, struct sk_buff *oskb)
|
||||
{
|
||||
const struct j1939_sk_buff_cb *oskcb = j1939_skb_to_cb(oskb);
|
||||
struct j1939_sk_buff_cb *skcb;
|
||||
enum skb_drop_reason reason;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (oskb->sk == &jsk->sk)
|
||||
@@ -331,8 +332,8 @@ static void j1939_sk_recv_one(struct j1939_sock *jsk, struct sk_buff *oskb)
|
||||
if (skb->sk)
|
||||
skcb->msg_flags |= MSG_DONTROUTE;
|
||||
|
||||
if (sock_queue_rcv_skb(&jsk->sk, skb) < 0)
|
||||
kfree_skb(skb);
|
||||
if (sock_queue_rcv_skb_reason(&jsk->sk, skb, &reason) < 0)
|
||||
sk_skb_reason_drop(&jsk->sk, skb, reason);
|
||||
}
|
||||
|
||||
bool j1939_sk_recv_match(struct j1939_priv *priv, struct j1939_sk_buff_cb *skcb)
|
||||
|
||||
+3
-2
@@ -129,6 +129,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||
{
|
||||
struct sock *sk = (struct sock *)data;
|
||||
struct raw_sock *ro = raw_sk(sk);
|
||||
enum skb_drop_reason reason;
|
||||
struct sockaddr_can *addr;
|
||||
struct sk_buff *skb;
|
||||
unsigned int *pflags;
|
||||
@@ -205,8 +206,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||
if (oskb->sk == sk)
|
||||
*pflags |= MSG_CONFIRM;
|
||||
|
||||
if (sock_queue_rcv_skb(sk, skb) < 0)
|
||||
kfree_skb(skb);
|
||||
if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0)
|
||||
sk_skb_reason_drop(sk, skb, reason);
|
||||
}
|
||||
|
||||
static int raw_enable_filters(struct net *net, struct net_device *dev,
|
||||
|
||||
Reference in New Issue
Block a user