Commit 262d7a52 authored by Jimmy Assarsson's avatar Jimmy Assarsson Committed by Marc Kleine-Budde
Browse files

can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt



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: 26ad340e ("can: kvaser_pciefd: Add driver for Kvaser PCIEcan devices")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJimmy Assarsson <extja@kvaser.com>
Link: https://lore.kernel.org/r/20230516134318.104279-6-extja@kvaser.com


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent c589557d
Loading
Loading
Loading
Loading
+4 −17
Original line number Diff line number Diff line
@@ -531,7 +531,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);

@@ -579,7 +579,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);
@@ -622,7 +622,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);
@@ -1015,8 +1015,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;
@@ -1443,9 +1442,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");