]> git.itanic.dy.fi Git - linux-stable/commitdiff
can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt
authorJimmy Assarsson <extja@kvaser.com>
Tue, 16 May 2023 13:43:17 +0000 (15:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 May 2023 16:36:54 +0000 (17:36 +0100)
commit 262d7a52ba27525e3c1203230c9f0524e48bbb34 upstream.

Under certain circumstances we send two EFLUSH commands, resulting in two
EFLUSH ack packets, while only expecting a single EFLUSH ack.
This can cause the driver Tx flush completion to get out of sync.

To avoid this problem, don't enable the "Transmit buffer flush done" (TFD)
interrupt and remove the code handling it.
Now we only send EFLUSH command after receiving status packet with
"Init detected" (IDET) bit set.

Fixes: 26ad340e582d ("can: kvaser_pciefd: Add driver for Kvaser PCIEcan devices")
Cc: stable@vger.kernel.org
Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
Link: https://lore.kernel.org/r/20230516134318.104279-6-extja@kvaser.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/can/kvaser_pciefd.c

index 98676fda9b8c55a37d72c36fb3f5a0b8ad50bf45..6b3ed0782418ac63c8cc7d083f33ab7cb0973d72 100644 (file)
@@ -533,7 +533,7 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
              KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
              KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
              KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
-             KVASER_PCIEFD_KCAN_IRQ_TAR | KVASER_PCIEFD_KCAN_IRQ_TFD;
+             KVASER_PCIEFD_KCAN_IRQ_TAR;
 
        iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
@@ -581,7 +581,7 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
 
        spin_lock_irqsave(&can->lock, irq);
        iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
        status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
@@ -624,7 +624,7 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
        iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
        iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
 
-       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+       iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
        mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
@@ -1011,8 +1011,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
                SET_NETDEV_DEV(netdev, &pcie->pci->dev);
 
                iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-               iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD |
-                         KVASER_PCIEFD_KCAN_IRQ_TFD,
+               iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
                          can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
                pcie->can[i] = can;
@@ -1441,9 +1440,6 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
                cmd = KVASER_PCIEFD_KCAN_CMD_AT;
                cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
                iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
-
-               iowrite32(KVASER_PCIEFD_KCAN_IRQ_TFD,
-                         can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
        } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
                   p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
                   cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
@@ -1732,15 +1728,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
        if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
                netdev_err(can->can.dev, "Tx FIFO overflow\n");
 
-       if (irq & KVASER_PCIEFD_KCAN_IRQ_TFD) {
-               u8 count = ioread32(can->reg_base +
-                                   KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
-
-               if (count == 0)
-                       iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
-                                 can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
-       }
-
        if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
                netdev_err(can->can.dev,
                           "Fail to change bittiming, when not in reset mode\n");