Skip to content

Commit 2d77bd6

Browse files
FaberFlorianmarckleinebudde
authored andcommitted
can: mscan: mscan_rx_poll(): fix rx path lockup when returning from polling to irq mode
Under load, the RX side of the mscan driver can get stuck while TX still works. Restarting the interface locks up the system. This behaviour could be reproduced reliably on a MPC5121e based system. The patch fixes the return value of the NAPI polling function (should be the number of processed packets, not constant 1) and the condition under which IRQs are enabled again after polling is finished. With this patch, no more lockups were observed over a test period of ten days. Fixes: afa17a5 ("net/can: add driver for mscan family & mpc52xx_mscan") Signed-off-by: Florian Faber <[email protected]> Cc: linux-stable <[email protected]> Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 2f361cd commit 2d77bd6

File tree

1 file changed

+10
-11
lines changed

1 file changed

+10
-11
lines changed

drivers/net/can/mscan/mscan.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
381381
struct net_device *dev = napi->dev;
382382
struct mscan_regs __iomem *regs = priv->reg_base;
383383
struct net_device_stats *stats = &dev->stats;
384-
int npackets = 0;
385-
int ret = 1;
384+
int work_done = 0;
386385
struct sk_buff *skb;
387386
struct can_frame *frame;
388387
u8 canrflg;
389388

390-
while (npackets < quota) {
389+
while (work_done < quota) {
391390
canrflg = in_8(&regs->canrflg);
392391
if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
393392
break;
@@ -408,18 +407,18 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
408407

409408
stats->rx_packets++;
410409
stats->rx_bytes += frame->can_dlc;
411-
npackets++;
410+
work_done++;
412411
netif_receive_skb(skb);
413412
}
414413

415-
if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
416-
napi_complete(&priv->napi);
417-
clear_bit(F_RX_PROGRESS, &priv->flags);
418-
if (priv->can.state < CAN_STATE_BUS_OFF)
419-
out_8(&regs->canrier, priv->shadow_canrier);
420-
ret = 0;
414+
if (work_done < quota) {
415+
if (likely(napi_complete_done(&priv->napi, work_done))) {
416+
clear_bit(F_RX_PROGRESS, &priv->flags);
417+
if (priv->can.state < CAN_STATE_BUS_OFF)
418+
out_8(&regs->canrier, priv->shadow_canrier);
419+
}
421420
}
422-
return ret;
421+
return work_done;
423422
}
424423

425424
static irqreturn_t mscan_isr(int irq, void *dev_id)

0 commit comments

Comments
 (0)