Commit de90869a authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-fixes-for-6.1-20221027' of...

Merge tag 'linux-can-fixes-for-6.1-20221027' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2022-10-27

Anssi Hannula fixes the use of the completions in the kvaser_usb
driver.

Biju Das contributes 2 patches for the rcar_canfd driver. A IRQ storm
that can be triggered by high CAN bus load and channel specific IRQ
handlers are fixed.

Yang Yingliang fixes the j1939 transport protocol by moving a
kfree_skb() out of a spin_lock_irqsave protected section.

* tag 'linux-can-fixes-for-6.1-20221027' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: j1939: transport: j1939_session_skb_drop_old(): spin_unlock_irqrestore() before kfree_skb()
  can: rcar_canfd: fix channel specific IRQ handling for RZ/G2L
  can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global FIFO receive
  can: kvaser_usb: Fix possible completions during init_completion
====================

Link: https://lore.kernel.org/r/20221027114356.1939821-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ef3556ee c3c06c61
...@@ -1157,11 +1157,13 @@ static void rcar_canfd_handle_global_receive(struct rcar_canfd_global *gpriv, u3 ...@@ -1157,11 +1157,13 @@ static void rcar_canfd_handle_global_receive(struct rcar_canfd_global *gpriv, u3
{ {
struct rcar_canfd_channel *priv = gpriv->ch[ch]; struct rcar_canfd_channel *priv = gpriv->ch[ch];
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
u32 sts; u32 sts, cc;
/* Handle Rx interrupts */ /* Handle Rx interrupts */
sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx)); sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx));
if (likely(sts & RCANFD_RFSTS_RFIF)) { cc = rcar_canfd_read(priv->base, RCANFD_RFCC(gpriv, ridx));
if (likely(sts & RCANFD_RFSTS_RFIF &&
cc & RCANFD_RFCC_RFIE)) {
if (napi_schedule_prep(&priv->napi)) { if (napi_schedule_prep(&priv->napi)) {
/* Disable Rx FIFO interrupts */ /* Disable Rx FIFO interrupts */
rcar_canfd_clear_bit(priv->base, rcar_canfd_clear_bit(priv->base,
...@@ -1244,11 +1246,9 @@ static void rcar_canfd_handle_channel_tx(struct rcar_canfd_global *gpriv, u32 ch ...@@ -1244,11 +1246,9 @@ static void rcar_canfd_handle_channel_tx(struct rcar_canfd_global *gpriv, u32 ch
static irqreturn_t rcar_canfd_channel_tx_interrupt(int irq, void *dev_id) static irqreturn_t rcar_canfd_channel_tx_interrupt(int irq, void *dev_id)
{ {
struct rcar_canfd_global *gpriv = dev_id; struct rcar_canfd_channel *priv = dev_id;
u32 ch;
for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_channel_tx(priv->gpriv, priv->channel);
rcar_canfd_handle_channel_tx(gpriv, ch);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1276,11 +1276,9 @@ static void rcar_canfd_handle_channel_err(struct rcar_canfd_global *gpriv, u32 c ...@@ -1276,11 +1276,9 @@ static void rcar_canfd_handle_channel_err(struct rcar_canfd_global *gpriv, u32 c
static irqreturn_t rcar_canfd_channel_err_interrupt(int irq, void *dev_id) static irqreturn_t rcar_canfd_channel_err_interrupt(int irq, void *dev_id)
{ {
struct rcar_canfd_global *gpriv = dev_id; struct rcar_canfd_channel *priv = dev_id;
u32 ch;
for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_channel_err(priv->gpriv, priv->channel);
rcar_canfd_handle_channel_err(gpriv, ch);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1721,6 +1719,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1721,6 +1719,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
priv->ndev = ndev; priv->ndev = ndev;
priv->base = gpriv->base; priv->base = gpriv->base;
priv->channel = ch; priv->channel = ch;
priv->gpriv = gpriv;
priv->can.clock.freq = fcan_freq; priv->can.clock.freq = fcan_freq;
dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq);
...@@ -1749,7 +1748,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1749,7 +1748,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
} }
err = devm_request_irq(&pdev->dev, err_irq, err = devm_request_irq(&pdev->dev, err_irq,
rcar_canfd_channel_err_interrupt, 0, rcar_canfd_channel_err_interrupt, 0,
irq_name, gpriv); irq_name, priv);
if (err) { if (err) {
dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n", dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n",
err_irq, err); err_irq, err);
...@@ -1763,7 +1762,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1763,7 +1762,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
} }
err = devm_request_irq(&pdev->dev, tx_irq, err = devm_request_irq(&pdev->dev, tx_irq,
rcar_canfd_channel_tx_interrupt, 0, rcar_canfd_channel_tx_interrupt, 0,
irq_name, gpriv); irq_name, priv);
if (err) { if (err) {
dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n", dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n",
tx_irq, err); tx_irq, err);
...@@ -1789,7 +1788,6 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1789,7 +1788,6 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
priv->can.do_set_mode = rcar_canfd_do_set_mode; priv->can.do_set_mode = rcar_canfd_do_set_mode;
priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter;
priv->gpriv = gpriv;
SET_NETDEV_DEV(ndev, &pdev->dev); SET_NETDEV_DEV(ndev, &pdev->dev);
netif_napi_add_weight(ndev, &priv->napi, rcar_canfd_rx_poll, netif_napi_add_weight(ndev, &priv->napi, rcar_canfd_rx_poll,
......
...@@ -1875,7 +1875,7 @@ static int kvaser_usb_hydra_start_chip(struct kvaser_usb_net_priv *priv) ...@@ -1875,7 +1875,7 @@ static int kvaser_usb_hydra_start_chip(struct kvaser_usb_net_priv *priv)
{ {
int err; int err;
init_completion(&priv->start_comp); reinit_completion(&priv->start_comp);
err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_START_CHIP_REQ, err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_START_CHIP_REQ,
priv->channel); priv->channel);
...@@ -1893,7 +1893,7 @@ static int kvaser_usb_hydra_stop_chip(struct kvaser_usb_net_priv *priv) ...@@ -1893,7 +1893,7 @@ static int kvaser_usb_hydra_stop_chip(struct kvaser_usb_net_priv *priv)
{ {
int err; int err;
init_completion(&priv->stop_comp); reinit_completion(&priv->stop_comp);
/* Make sure we do not report invalid BUS_OFF from CMD_CHIP_STATE_EVENT /* Make sure we do not report invalid BUS_OFF from CMD_CHIP_STATE_EVENT
* see comment in kvaser_usb_hydra_update_state() * see comment in kvaser_usb_hydra_update_state()
......
...@@ -1320,7 +1320,7 @@ static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv) ...@@ -1320,7 +1320,7 @@ static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv)
{ {
int err; int err;
init_completion(&priv->start_comp); reinit_completion(&priv->start_comp);
err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP, err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP,
priv->channel); priv->channel);
...@@ -1338,7 +1338,7 @@ static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv) ...@@ -1338,7 +1338,7 @@ static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv)
{ {
int err; int err;
init_completion(&priv->stop_comp); reinit_completion(&priv->stop_comp);
err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP,
priv->channel); priv->channel);
......
...@@ -342,10 +342,12 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) ...@@ -342,10 +342,12 @@ static void j1939_session_skb_drop_old(struct j1939_session *session)
__skb_unlink(do_skb, &session->skb_queue); __skb_unlink(do_skb, &session->skb_queue);
/* drop ref taken in j1939_session_skb_queue() */ /* drop ref taken in j1939_session_skb_queue() */
skb_unref(do_skb); skb_unref(do_skb);
spin_unlock_irqrestore(&session->skb_queue.lock, flags);
kfree_skb(do_skb); kfree_skb(do_skb);
} else {
spin_unlock_irqrestore(&session->skb_queue.lock, flags);
} }
spin_unlock_irqrestore(&session->skb_queue.lock, flags);
} }
void j1939_session_skb_queue(struct j1939_session *session, void j1939_session_skb_queue(struct j1939_session *session,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment