mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-21 03:33:59 +08:00
linux-can-fixes-for-5.15-20211017
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmFsjT8THG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqXJNCACBFemjdVEKUaWEjd10YvHaILdnEkge 6bj51eIpYy/aAfIqGLhhUOYiyVRlrTD4phJBSVl25jx0Vaf6UqXQ6Otd3GjJAV7j 16Hp8EvGc14cnx+rCPU471YUWyTrPl7YU9AoYKeBmbRmwh4i6HiJZ75AbG6xGvE8 2JZLmrF0QvpZRFfxE0uF5oVwjP9tOSvDmuFa6Me/JQ30CBrpxSalayizMvCO27eO k2PaXSCpfms2K2eSBTqcjcqjJV57izJzNVtPkcmgOcyB1gvbBmHD7Y2GiiJ6Uigg YkVEscsZNE1Wn/5p+sIS3pKDErsCsTgiAaopxCiaEsMLdv8b7HLecRGN =CfwZ -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-5.15-20211017' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2021-10-17 this is a pull request of 11 patches for net/master. The first 4 patches are by Ziyang Xuan and Zhang Changzhong and fix 1 use after free and 3 standard conformance problems in the j1939 CAN stack. The next 2 patches are by Ziyang Xuan and fix 2 concurrency problems in the ISOTP CAN stack. Yoshihiro Shimoda's patch for the rcar_can fix suspend/resume on not running CAN interfaces. Aswath Govindraju's patch for the m_can driver fixes access for MMIO devices. Zheyu Ma contributes a patch for the peak_pci driver to fix a use after free. Stephane Grosjean's 2 patches fix CAN error state handling in the peak_usb driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
bca69044af
@ -32,8 +32,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
|
||||
static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
|
||||
{
|
||||
struct m_can_plat_priv *priv = cdev_to_priv(cdev);
|
||||
void __iomem *src = priv->mram_base + offset;
|
||||
|
||||
ioread32_rep(priv->mram_base + offset, val, val_count);
|
||||
while (val_count--) {
|
||||
*(unsigned int *)val = ioread32(src);
|
||||
val += 4;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -51,8 +56,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
|
||||
const void *val, size_t val_count)
|
||||
{
|
||||
struct m_can_plat_priv *priv = cdev_to_priv(cdev);
|
||||
void __iomem *dst = priv->mram_base + offset;
|
||||
|
||||
iowrite32_rep(priv->base + offset, val, val_count);
|
||||
while (val_count--) {
|
||||
iowrite32(*(unsigned int *)val, dst);
|
||||
val += 4;
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -846,10 +846,12 @@ static int __maybe_unused rcar_can_suspend(struct device *dev)
|
||||
struct rcar_can_priv *priv = netdev_priv(ndev);
|
||||
u16 ctlr;
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
netif_stop_queue(ndev);
|
||||
netif_device_detach(ndev);
|
||||
}
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
netif_device_detach(ndev);
|
||||
|
||||
ctlr = readw(&priv->regs->ctlr);
|
||||
ctlr |= RCAR_CAN_CTLR_CANM_HALT;
|
||||
writew(ctlr, &priv->regs->ctlr);
|
||||
@ -868,6 +870,9 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
|
||||
u16 ctlr;
|
||||
int err;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
|
||||
err = clk_enable(priv->clk);
|
||||
if (err) {
|
||||
netdev_err(ndev, "clk_enable() failed, error %d\n", err);
|
||||
@ -881,10 +886,9 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
|
||||
writew(ctlr, &priv->regs->ctlr);
|
||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
netif_device_attach(ndev);
|
||||
netif_start_queue(ndev);
|
||||
}
|
||||
netif_device_attach(ndev);
|
||||
netif_start_queue(ndev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -752,16 +752,15 @@ static void peak_pci_remove(struct pci_dev *pdev)
|
||||
struct net_device *prev_dev = chan->prev_dev;
|
||||
|
||||
dev_info(&pdev->dev, "removing device %s\n", dev->name);
|
||||
/* do that only for first channel */
|
||||
if (!prev_dev && chan->pciec_card)
|
||||
peak_pciec_remove(chan->pciec_card);
|
||||
unregister_sja1000dev(dev);
|
||||
free_sja1000dev(dev);
|
||||
dev = prev_dev;
|
||||
|
||||
if (!dev) {
|
||||
/* do that only for first channel */
|
||||
if (chan->pciec_card)
|
||||
peak_pciec_remove(chan->pciec_card);
|
||||
if (!dev)
|
||||
break;
|
||||
}
|
||||
priv = netdev_priv(dev);
|
||||
chan = priv->priv;
|
||||
}
|
||||
|
@ -551,11 +551,10 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if,
|
||||
} else if (sm->channel_p_w_b & PUCAN_BUS_WARNING) {
|
||||
new_state = CAN_STATE_ERROR_WARNING;
|
||||
} else {
|
||||
/* no error bit (so, no error skb, back to active state) */
|
||||
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
/* back to (or still in) ERROR_ACTIVE state */
|
||||
new_state = CAN_STATE_ERROR_ACTIVE;
|
||||
pdev->bec.txerr = 0;
|
||||
pdev->bec.rxerr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* state hasn't changed */
|
||||
@ -568,8 +567,7 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if,
|
||||
|
||||
/* allocate an skb to store the error frame */
|
||||
skb = alloc_can_err_skb(netdev, &cf);
|
||||
if (skb)
|
||||
can_change_state(netdev, cf, tx_state, rx_state);
|
||||
can_change_state(netdev, cf, tx_state, rx_state);
|
||||
|
||||
/* things must be done even in case of OOM */
|
||||
if (new_state == CAN_STATE_BUS_OFF)
|
||||
|
@ -121,7 +121,7 @@ enum {
|
||||
struct tpcon {
|
||||
int idx;
|
||||
int len;
|
||||
u8 state;
|
||||
u32 state;
|
||||
u8 bs;
|
||||
u8 sn;
|
||||
u8 ll_dl;
|
||||
@ -848,6 +848,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct isotp_sock *so = isotp_sk(sk);
|
||||
u32 old_state = so->tx.state;
|
||||
struct sk_buff *skb;
|
||||
struct net_device *dev;
|
||||
struct canfd_frame *cf;
|
||||
@ -860,45 +861,55 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/* we do not support multiple buffers - for now */
|
||||
if (so->tx.state != ISOTP_IDLE || wq_has_sleeper(&so->wait)) {
|
||||
if (msg->msg_flags & MSG_DONTWAIT)
|
||||
return -EAGAIN;
|
||||
if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE ||
|
||||
wq_has_sleeper(&so->wait)) {
|
||||
if (msg->msg_flags & MSG_DONTWAIT) {
|
||||
err = -EAGAIN;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* wait for complete transmission of current pdu */
|
||||
wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
|
||||
err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!size || size > MAX_MSG_LENGTH)
|
||||
return -EINVAL;
|
||||
if (!size || size > MAX_MSG_LENGTH) {
|
||||
err = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* take care of a potential SF_DL ESC offset for TX_DL > 8 */
|
||||
off = (so->tx.ll_dl > CAN_MAX_DLEN) ? 1 : 0;
|
||||
|
||||
/* does the given data fit into a single frame for SF_BROADCAST? */
|
||||
if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) &&
|
||||
(size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off))
|
||||
return -EINVAL;
|
||||
(size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) {
|
||||
err = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err = memcpy_from_msg(so->tx.buf, msg, size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto err_out;
|
||||
|
||||
dev = dev_get_by_index(sock_net(sk), so->ifindex);
|
||||
if (!dev)
|
||||
return -ENXIO;
|
||||
if (!dev) {
|
||||
err = -ENXIO;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv),
|
||||
msg->msg_flags & MSG_DONTWAIT, &err);
|
||||
if (!skb) {
|
||||
dev_put(dev);
|
||||
return err;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
can_skb_reserve(skb);
|
||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||
can_skb_prv(skb)->skbcnt = 0;
|
||||
|
||||
so->tx.state = ISOTP_SENDING;
|
||||
so->tx.len = size;
|
||||
so->tx.idx = 0;
|
||||
|
||||
@ -954,7 +965,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
if (err) {
|
||||
pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
|
||||
__func__, ERR_PTR(err));
|
||||
return err;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (wait_tx_done) {
|
||||
@ -963,6 +974,13 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
}
|
||||
|
||||
return size;
|
||||
|
||||
err_out:
|
||||
so->tx.state = old_state;
|
||||
if (so->tx.state == ISOTP_IDLE)
|
||||
wake_up_interruptible(&so->wait);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
||||
|
@ -330,6 +330,7 @@ int j1939_session_activate(struct j1939_session *session);
|
||||
void j1939_tp_schedule_txtimer(struct j1939_session *session, int msec);
|
||||
void j1939_session_timers_cancel(struct j1939_session *session);
|
||||
|
||||
#define J1939_MIN_TP_PACKET_SIZE 9
|
||||
#define J1939_MAX_TP_PACKET_SIZE (7 * 0xff)
|
||||
#define J1939_MAX_ETP_PACKET_SIZE (7 * 0x00ffffff)
|
||||
|
||||
|
@ -249,11 +249,14 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
|
||||
struct j1939_priv *priv, *priv_new;
|
||||
int ret;
|
||||
|
||||
priv = j1939_priv_get_by_ndev(ndev);
|
||||
spin_lock(&j1939_netdev_lock);
|
||||
priv = j1939_priv_get_by_ndev_locked(ndev);
|
||||
if (priv) {
|
||||
kref_get(&priv->rx_kref);
|
||||
spin_unlock(&j1939_netdev_lock);
|
||||
return priv;
|
||||
}
|
||||
spin_unlock(&j1939_netdev_lock);
|
||||
|
||||
priv = j1939_priv_create(ndev);
|
||||
if (!priv)
|
||||
@ -269,10 +272,10 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
|
||||
/* Someone was faster than us, use their priv and roll
|
||||
* back our's.
|
||||
*/
|
||||
kref_get(&priv_new->rx_kref);
|
||||
spin_unlock(&j1939_netdev_lock);
|
||||
dev_put(ndev);
|
||||
kfree(priv);
|
||||
kref_get(&priv_new->rx_kref);
|
||||
return priv_new;
|
||||
}
|
||||
j1939_priv_set(ndev, priv);
|
||||
|
@ -1237,12 +1237,11 @@ static enum hrtimer_restart j1939_tp_rxtimer(struct hrtimer *hrtimer)
|
||||
session->err = -ETIME;
|
||||
j1939_session_deactivate(session);
|
||||
} else {
|
||||
netdev_alert(priv->ndev, "%s: 0x%p: rx timeout, send abort\n",
|
||||
__func__, session);
|
||||
|
||||
j1939_session_list_lock(session->priv);
|
||||
if (session->state >= J1939_SESSION_ACTIVE &&
|
||||
session->state < J1939_SESSION_ACTIVE_MAX) {
|
||||
netdev_alert(priv->ndev, "%s: 0x%p: rx timeout, send abort\n",
|
||||
__func__, session);
|
||||
j1939_session_get(session);
|
||||
hrtimer_start(&session->rxtimer,
|
||||
ms_to_ktime(J1939_XTP_ABORT_TIMEOUT_MS),
|
||||
@ -1609,6 +1608,8 @@ j1939_session *j1939_xtp_rx_rts_session_new(struct j1939_priv *priv,
|
||||
abort = J1939_XTP_ABORT_FAULT;
|
||||
else if (len > priv->tp_max_packet_size)
|
||||
abort = J1939_XTP_ABORT_RESOURCE;
|
||||
else if (len < J1939_MIN_TP_PACKET_SIZE)
|
||||
abort = J1939_XTP_ABORT_FAULT;
|
||||
}
|
||||
|
||||
if (abort != J1939_XTP_NO_ABORT) {
|
||||
@ -1789,6 +1790,7 @@ static void j1939_xtp_rx_dpo(struct j1939_priv *priv, struct sk_buff *skb,
|
||||
static void j1939_xtp_rx_dat_one(struct j1939_session *session,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
enum j1939_xtp_abort abort = J1939_XTP_ABORT_FAULT;
|
||||
struct j1939_priv *priv = session->priv;
|
||||
struct j1939_sk_buff_cb *skcb, *se_skcb;
|
||||
struct sk_buff *se_skb = NULL;
|
||||
@ -1803,9 +1805,11 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
|
||||
|
||||
skcb = j1939_skb_to_cb(skb);
|
||||
dat = skb->data;
|
||||
if (skb->len <= 1)
|
||||
if (skb->len != 8) {
|
||||
/* makes no sense */
|
||||
abort = J1939_XTP_ABORT_UNEXPECTED_DATA;
|
||||
goto out_session_cancel;
|
||||
}
|
||||
|
||||
switch (session->last_cmd) {
|
||||
case 0xff:
|
||||
@ -1904,7 +1908,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
|
||||
out_session_cancel:
|
||||
kfree_skb(se_skb);
|
||||
j1939_session_timers_cancel(session);
|
||||
j1939_session_cancel(session, J1939_XTP_ABORT_FAULT);
|
||||
j1939_session_cancel(session, abort);
|
||||
j1939_session_put(session);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user