linux-can-fixes-for-6.17-20250910
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEn/sM2K9nqF/8FWzzDHRl3/mQkZwFAmjBpO8THG1rbEBwZW5n dXRyb25peC5kZQAKCRAMdGXf+ZCRnJOOB/9r35uZBD1+ZZVpvoByhil8XY7K42Vv LrARJ8+kh1Q6mcuB4V/176GBPJ7JabSUTGqvqvYbJBAB5obONhLU5Bkb/7lM2z1G MOUe0DMiBP+J3K8zqXcEKhqeW0qQO6pqfnv8iIj97Kxwd5JRPJq8pMpCIC/RLzOY Ot7+fcsE+cSZt9VumnQTx/S1fzGoY1C9VCglSr9B0O6IiTZZBIPNg8EwIGvbm7oh uofnFRocRZaWQ6OErdRSTLK4hu11DeFUmEAA6YN2ikpAdshUsf3U8HYaz2LIEEuu zGflFXrMekXqDod1SvhklLPUY/ssC11dUon+4Cgz/yK6I+lFvD/cuLIP =/YxL -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-6.17-20250910' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2025-09-10 The 1st patch is by Alex Tran and fixes the Documentation of the struct bcm_msg_head. Davide Caratti's patch enabled the VCAN driver as a module for the Linux self tests. Tetsuo Handa contributes 3 patches that fix various problems in the CAN j1939 protocol. Anssi Hannula's patch fixes a potential use-after-free in the xilinx_can driver. Geert Uytterhoeven's patch fixes the rcan_can's suspend to RAM on R-Car Gen3 using PSCI. * tag 'linux-can-fixes-for-6.17-20250910' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: rcar_can: rcar_can_resume(): fix s2ram with PSCI can: xilinx_can: xcan_write_frame(): fix use-after-free of transmitted SKB can: j1939: j1939_local_ecu_get(): undo increment when j1939_local_ecu_get() fails can: j1939: j1939_sk_bind(): call j1939_priv_put() immediately when j1939_local_ecu_get() failed can: j1939: implement NETDEV_UNREGISTER notification handler selftests: can: enable CONFIG_CAN_VCAN as a module docs: networking: can: change bcm_msg_head frames member to support flexible array ==================== Link: https://patch.msgid.link/20250910162907.948454-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
ccf78f7f05
|
@ -742,7 +742,7 @@ The broadcast manager sends responses to user space in the same form:
|
||||||
struct timeval ival1, ival2; /* count and subsequent interval */
|
struct timeval ival1, ival2; /* count and subsequent interval */
|
||||||
canid_t can_id; /* unique can_id for task */
|
canid_t can_id; /* unique can_id for task */
|
||||||
__u32 nframes; /* number of can_frames following */
|
__u32 nframes; /* number of can_frames following */
|
||||||
struct can_frame frames[0];
|
struct can_frame frames[];
|
||||||
};
|
};
|
||||||
|
|
||||||
The aligned payload 'frames' uses the same basic CAN frame structure defined
|
The aligned payload 'frames' uses the same basic CAN frame structure defined
|
||||||
|
|
|
@ -861,7 +861,6 @@ static int rcar_can_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct net_device *ndev = dev_get_drvdata(dev);
|
struct net_device *ndev = dev_get_drvdata(dev);
|
||||||
struct rcar_can_priv *priv = netdev_priv(ndev);
|
struct rcar_can_priv *priv = netdev_priv(ndev);
|
||||||
u16 ctlr;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!netif_running(ndev))
|
if (!netif_running(ndev))
|
||||||
|
@ -873,12 +872,7 @@ static int rcar_can_resume(struct device *dev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctlr = readw(&priv->regs->ctlr);
|
rcar_can_start(ndev);
|
||||||
ctlr &= ~RCAR_CAN_CTLR_SLPM;
|
|
||||||
writew(ctlr, &priv->regs->ctlr);
|
|
||||||
ctlr &= ~RCAR_CAN_CTLR_CANM;
|
|
||||||
writew(ctlr, &priv->regs->ctlr);
|
|
||||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
|
||||||
|
|
||||||
netif_device_attach(ndev);
|
netif_device_attach(ndev);
|
||||||
netif_start_queue(ndev);
|
netif_start_queue(ndev);
|
||||||
|
|
|
@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
|
||||||
dlc |= XCAN_DLCR_EDL_MASK;
|
dlc |= XCAN_DLCR_EDL_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
|
|
||||||
(priv->devtype.flags & XCAN_FLAG_TXFEMP))
|
|
||||||
can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
|
|
||||||
else
|
|
||||||
can_put_echo_skb(skb, ndev, 0, 0);
|
|
||||||
|
|
||||||
priv->tx_head++;
|
|
||||||
|
|
||||||
priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
|
priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
|
||||||
/* If the CAN frame is RTR frame this write triggers transmission
|
/* If the CAN frame is RTR frame this write triggers transmission
|
||||||
* (not on CAN FD)
|
* (not on CAN FD)
|
||||||
|
@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
|
||||||
data[1]);
|
data[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
|
||||||
|
(priv->devtype.flags & XCAN_FLAG_TXFEMP))
|
||||||
|
can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
|
||||||
|
else
|
||||||
|
can_put_echo_skb(skb, ndev, 0, 0);
|
||||||
|
|
||||||
|
priv->tx_head++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)
|
||||||
if (!ecu)
|
if (!ecu)
|
||||||
ecu = j1939_ecu_create_locked(priv, name);
|
ecu = j1939_ecu_create_locked(priv, name);
|
||||||
err = PTR_ERR_OR_ZERO(ecu);
|
err = PTR_ERR_OR_ZERO(ecu);
|
||||||
if (err)
|
if (err) {
|
||||||
|
if (j1939_address_is_unicast(sa))
|
||||||
|
priv->ents[sa].nusers--;
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ecu->nusers++;
|
ecu->nusers++;
|
||||||
/* TODO: do we care if ecu->addr != sa? */
|
/* TODO: do we care if ecu->addr != sa? */
|
||||||
|
|
|
@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);
|
||||||
|
|
||||||
/* notify/alert all j1939 sockets bound to ifindex */
|
/* notify/alert all j1939 sockets bound to ifindex */
|
||||||
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
|
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
|
||||||
|
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv);
|
||||||
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
|
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
|
||||||
void j1939_tp_init(struct j1939_priv *priv);
|
void j1939_tp_init(struct j1939_priv *priv);
|
||||||
|
|
||||||
|
|
|
@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,
|
||||||
j1939_sk_netdev_event_netdown(priv);
|
j1939_sk_netdev_event_netdown(priv);
|
||||||
j1939_ecu_unmap_all(priv);
|
j1939_ecu_unmap_all(priv);
|
||||||
break;
|
break;
|
||||||
|
case NETDEV_UNREGISTER:
|
||||||
|
j1939_sk_netdev_event_unregister(priv);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
j1939_priv_put(priv);
|
j1939_priv_put(priv);
|
||||||
|
|
|
@ -521,6 +521,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
|
||||||
ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa);
|
ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
j1939_netdev_stop(priv);
|
j1939_netdev_stop(priv);
|
||||||
|
jsk->priv = NULL;
|
||||||
|
synchronize_rcu();
|
||||||
|
j1939_priv_put(priv);
|
||||||
goto out_release_sock;
|
goto out_release_sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,6 +1303,55 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
|
||||||
read_unlock_bh(&priv->j1939_socks_lock);
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv)
|
||||||
|
{
|
||||||
|
struct sock *sk;
|
||||||
|
struct j1939_sock *jsk;
|
||||||
|
bool wait_rcu = false;
|
||||||
|
|
||||||
|
rescan: /* The caller is holding a ref on this "priv" via j1939_priv_get_by_ndev(). */
|
||||||
|
read_lock_bh(&priv->j1939_socks_lock);
|
||||||
|
list_for_each_entry(jsk, &priv->j1939_socks, list) {
|
||||||
|
/* Skip if j1939_jsk_add() is not called on this socket. */
|
||||||
|
if (!(jsk->state & J1939_SOCK_BOUND))
|
||||||
|
continue;
|
||||||
|
sk = &jsk->sk;
|
||||||
|
sock_hold(sk);
|
||||||
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
|
/* Check if j1939_jsk_del() is not yet called on this socket after holding
|
||||||
|
* socket's lock, for both j1939_sk_bind() and j1939_sk_release() call
|
||||||
|
* j1939_jsk_del() with socket's lock held.
|
||||||
|
*/
|
||||||
|
lock_sock(sk);
|
||||||
|
if (jsk->state & J1939_SOCK_BOUND) {
|
||||||
|
/* Neither j1939_sk_bind() nor j1939_sk_release() called j1939_jsk_del().
|
||||||
|
* Make this socket no longer bound, by pretending as if j1939_sk_bind()
|
||||||
|
* dropped old references but did not get new references.
|
||||||
|
*/
|
||||||
|
j1939_jsk_del(priv, jsk);
|
||||||
|
j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa);
|
||||||
|
j1939_netdev_stop(priv);
|
||||||
|
/* Call j1939_priv_put() now and prevent j1939_sk_sock_destruct() from
|
||||||
|
* calling the corresponding j1939_priv_put().
|
||||||
|
*
|
||||||
|
* j1939_sk_sock_destruct() is supposed to call j1939_priv_put() after
|
||||||
|
* an RCU grace period. But since the caller is holding a ref on this
|
||||||
|
* "priv", we can defer synchronize_rcu() until immediately before
|
||||||
|
* the caller calls j1939_priv_put().
|
||||||
|
*/
|
||||||
|
j1939_priv_put(priv);
|
||||||
|
jsk->priv = NULL;
|
||||||
|
wait_rcu = true;
|
||||||
|
}
|
||||||
|
release_sock(sk);
|
||||||
|
sock_put(sk);
|
||||||
|
goto rescan;
|
||||||
|
}
|
||||||
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
|
if (wait_rcu)
|
||||||
|
synchronize_rcu();
|
||||||
|
}
|
||||||
|
|
||||||
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
|
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
CONFIG_CAN=m
|
||||||
|
CONFIG_CAN_DEV=m
|
||||||
|
CONFIG_CAN_VCAN=m
|
Loading…
Reference in New Issue