netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 0/2] pull-request: can 2024-12-18
@ 2024-12-18 12:10 Marc Kleine-Budde
  2024-12-18 12:10 ` [PATCH net 1/2] can: m_can: set init flag earlier in probe Marc Kleine-Budde
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2024-12-18 12:10 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, linux-can, kernel

Hello netdev-team,

this is a pull request of 21 patches for net/master.

There are 2 patches by Matthias Schiffer for the m_can_pci driver that
handles the m_can cores found on the Intel Elkhart Lake processor.
They fix the initialization and the interrupt handling under high CAN
bus load.

regards,
Marc

---

The following changes since commit 954a2b40719a21e763a1bba2f0da92347e058fce:

  rtnetlink: Try the outer netns attribute in rtnl_get_peer_net(). (2024-12-17 17:54:18 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git tags/linux-can-fixes-for-6.13-20241218

for you to fetch changes up to 87f54c12195150fec052f6a5458fcecdda5ec62f:

  Merge patch series "can: m_can: set init flag earlier in probe" (2024-12-18 09:32:14 +0100)

----------------------------------------------------------------
linux-can-fixes-for-6.13-20241218

----------------------------------------------------------------
Marc Kleine-Budde (1):
      Merge patch series "can: m_can: set init flag earlier in probe"

Matthias Schiffer (2):
      can: m_can: set init flag earlier in probe
      can: m_can: fix missed interrupts with m_can_pci

 drivers/net/can/m_can/m_can.c     | 36 ++++++++++++++++++++++++++----------
 drivers/net/can/m_can/m_can.h     |  1 +
 drivers/net/can/m_can/m_can_pci.c |  1 +
 3 files changed, 28 insertions(+), 10 deletions(-)


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 1/2] can: m_can: set init flag earlier in probe
  2024-12-18 12:10 [PATCH net 0/2] pull-request: can 2024-12-18 Marc Kleine-Budde
@ 2024-12-18 12:10 ` Marc Kleine-Budde
  2024-12-19  2:00   ` patchwork-bot+netdevbpf
  2024-12-18 12:10 ` [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci Marc Kleine-Budde
  2024-12-19  1:54 ` [PATCH net 0/2] pull-request: can 2024-12-18 Jakub Kicinski
  2 siblings, 1 reply; 7+ messages in thread
From: Marc Kleine-Budde @ 2024-12-18 12:10 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Matthias Schiffer,
	Markus Schneider-Pargmann, Marc Kleine-Budde

From: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>

While an m_can controller usually already has the init flag from a
hardware reset, no such reset happens on the integrated m_can_pci of the
Intel Elkhart Lake. If the CAN controller is found in an active state,
m_can_dev_setup() would fail because m_can_niso_supported() calls
m_can_cccr_update_bits(), which refuses to modify any other configuration
bits when CCCR_INIT is not set.

To avoid this issue, set CCCR_INIT before attempting to modify any other
configuration flags.

Fixes: cd5a46ce6fa6 ("can: m_can: don't enable transceiver when probing")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Reviewed-by: Markus Schneider-Pargmann <msp@baylibre.com>
Link: https://patch.msgid.link/e247f331cb72829fcbdfda74f31a59cbad1a6006.1728288535.git.matthias.schiffer@ew.tq-group.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/m_can/m_can.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 533bcb77c9f9..67c404fbe166 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1695,6 +1695,14 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
 		return -EINVAL;
 	}
 
+	/* Write the INIT bit, in case no hardware reset has happened before
+	 * the probe (for example, it was observed that the Intel Elkhart Lake
+	 * SoCs do not properly reset the CAN controllers on reboot)
+	 */
+	err = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+	if (err)
+		return err;
+
 	if (!cdev->is_peripheral)
 		netif_napi_add(dev, &cdev->napi, m_can_poll);
 
@@ -1746,11 +1754,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
 		return -EINVAL;
 	}
 
-	/* Forcing standby mode should be redundant, as the chip should be in
-	 * standby after a reset. Write the INIT bit anyways, should the chip
-	 * be configured by previous stage.
-	 */
-	return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+	return 0;
 }
 
 static void m_can_stop(struct net_device *dev)

base-commit: 954a2b40719a21e763a1bba2f0da92347e058fce
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci
  2024-12-18 12:10 [PATCH net 0/2] pull-request: can 2024-12-18 Marc Kleine-Budde
  2024-12-18 12:10 ` [PATCH net 1/2] can: m_can: set init flag earlier in probe Marc Kleine-Budde
@ 2024-12-18 12:10 ` Marc Kleine-Budde
  2024-12-19  1:51   ` Jakub Kicinski
  2024-12-19  1:54 ` [PATCH net 0/2] pull-request: can 2024-12-18 Jakub Kicinski
  2 siblings, 1 reply; 7+ messages in thread
From: Marc Kleine-Budde @ 2024-12-18 12:10 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Matthias Schiffer,
	Markus Schneider-Pargmann, Marc Kleine-Budde

From: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>

The interrupt line of PCI devices is interpreted as edge-triggered,
however the interrupt signal of the m_can controller integrated in Intel
Elkhart Lake CPUs appears to be generated level-triggered.

Consider the following sequence of events:

- IR register is read, interrupt X is set
- A new interrupt Y is triggered in the m_can controller
- IR register is written to acknowledge interrupt X. Y remains set in IR

As at no point in this sequence no interrupt flag is set in IR, the
m_can interrupt line will never become deasserted, and no edge will ever
be observed to trigger another run of the ISR. This was observed to
result in the TX queue of the EHL m_can to get stuck under high load,
because frames were queued to the hardware in m_can_start_xmit(), but
m_can_finish_tx() was never run to account for their successful
transmission.

On an Elkhart Lake based board with the two CAN interfaces connected to
each other, the following script can reproduce the issue:

    ip link set can0 up type can bitrate 1000000
    ip link set can1 up type can bitrate 1000000

    cangen can0 -g 2 -I 000 -L 8 &
    cangen can0 -g 2 -I 001 -L 8 &
    cangen can0 -g 2 -I 002 -L 8 &
    cangen can0 -g 2 -I 003 -L 8 &
    cangen can0 -g 2 -I 004 -L 8 &
    cangen can0 -g 2 -I 005 -L 8 &
    cangen can0 -g 2 -I 006 -L 8 &
    cangen can0 -g 2 -I 007 -L 8 &

    cangen can1 -g 2 -I 100 -L 8 &
    cangen can1 -g 2 -I 101 -L 8 &
    cangen can1 -g 2 -I 102 -L 8 &
    cangen can1 -g 2 -I 103 -L 8 &
    cangen can1 -g 2 -I 104 -L 8 &
    cangen can1 -g 2 -I 105 -L 8 &
    cangen can1 -g 2 -I 106 -L 8 &
    cangen can1 -g 2 -I 107 -L 8 &

    stress-ng --matrix 0 &

To fix the issue, repeatedly read and acknowledge interrupts at the
start of the ISR until no interrupt flags are set, so the next incoming
interrupt will also result in an edge on the interrupt line.

While we have received a report that even with this patch, the TX queue
can become stuck under certain (currently unknown) circumstances on the
Elkhart Lake, this patch completely fixes the issue with the above
reproducer, and it is unclear whether the remaining issue has a similar
cause at all.

Fixes: cab7ffc0324f ("can: m_can: add PCI glue driver for Intel Elkhart Lake")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Reviewed-by: Markus Schneider-Pargmann <msp@baylibre.com>
Link: https://patch.msgid.link/fdf0439c51bcb3a46c21e9fb21c7f1d06363be84.1728288535.git.matthias.schiffer@ew.tq-group.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/m_can/m_can.c     | 22 +++++++++++++++++-----
 drivers/net/can/m_can/m_can.h     |  1 +
 drivers/net/can/m_can/m_can_pci.c |  1 +
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 67c404fbe166..97cd8bbf2e32 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1220,20 +1220,32 @@ static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir)
 static int m_can_interrupt_handler(struct m_can_classdev *cdev)
 {
 	struct net_device *dev = cdev->net;
-	u32 ir;
+	u32 ir = 0, ir_read;
 	int ret;
 
 	if (pm_runtime_suspended(cdev->dev))
 		return IRQ_NONE;
 
-	ir = m_can_read(cdev, M_CAN_IR);
+	/* The m_can controller signals its interrupt status as a level, but
+	 * depending in the integration the CPU may interpret the signal as
+	 * edge-triggered (for example with m_can_pci). For these
+	 * edge-triggered integrations, we must observe that IR is 0 at least
+	 * once to be sure that the next interrupt will generate an edge.
+	 */
+	while ((ir_read = m_can_read(cdev, M_CAN_IR)) != 0) {
+		ir |= ir_read;
+
+		/* ACK all irqs */
+		m_can_write(cdev, M_CAN_IR, ir);
+
+		if (!cdev->irq_edge_triggered)
+			break;
+	}
+
 	m_can_coalescing_update(cdev, ir);
 	if (!ir)
 		return IRQ_NONE;
 
-	/* ACK all irqs */
-	m_can_write(cdev, M_CAN_IR, ir);
-
 	if (cdev->ops->clear_interrupts)
 		cdev->ops->clear_interrupts(cdev);
 
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index 92b2bd8628e6..ef39e8e527ab 100644
--- a/drivers/net/can/m_can/m_can.h
+++ b/drivers/net/can/m_can/m_can.h
@@ -99,6 +99,7 @@ struct m_can_classdev {
 	int pm_clock_support;
 	int pm_wake_source;
 	int is_peripheral;
+	bool irq_edge_triggered;
 
 	// Cached M_CAN_IE register content
 	u32 active_interrupts;
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index d72fe771dfc7..9ad7419f88f8 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -127,6 +127,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
 	mcan_class->pm_clock_support = 1;
 	mcan_class->pm_wake_source = 0;
 	mcan_class->can.clock.freq = id->driver_data;
+	mcan_class->irq_edge_triggered = true;
 	mcan_class->ops = &m_can_pci_ops;
 
 	pci_set_drvdata(pci, mcan_class);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci
  2024-12-18 12:10 ` [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci Marc Kleine-Budde
@ 2024-12-19  1:51   ` Jakub Kicinski
  0 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2024-12-19  1:51 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: netdev, davem, linux-can, kernel, Matthias Schiffer,
	Markus Schneider-Pargmann

On Wed, 18 Dec 2024 13:10:28 +0100 Marc Kleine-Budde wrote:
> +	while ((ir_read = m_can_read(cdev, M_CAN_IR)) != 0) {
> +		ir |= ir_read;
> +
> +		/* ACK all irqs */
> +		m_can_write(cdev, M_CAN_IR, ir);

Perhaps consider adding a cap on how many times this can loop 
as a follow up? Maybe if the HW is bad all bets are off, anyway,
but potential infinite loop inside an IRQ feels a little scary.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 0/2] pull-request: can 2024-12-18
  2024-12-18 12:10 [PATCH net 0/2] pull-request: can 2024-12-18 Marc Kleine-Budde
  2024-12-18 12:10 ` [PATCH net 1/2] can: m_can: set init flag earlier in probe Marc Kleine-Budde
  2024-12-18 12:10 ` [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci Marc Kleine-Budde
@ 2024-12-19  1:54 ` Jakub Kicinski
  2024-12-19  8:03   ` Marc Kleine-Budde
  2 siblings, 1 reply; 7+ messages in thread
From: Jakub Kicinski @ 2024-12-19  1:54 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: netdev, davem, linux-can, kernel

On Wed, 18 Dec 2024 13:10:26 +0100 Marc Kleine-Budde wrote:
> this is a pull request of 21 patches for net/master.

The "21" is just quantum state of 1 becoming 2? ;)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/2] can: m_can: set init flag earlier in probe
  2024-12-18 12:10 ` [PATCH net 1/2] can: m_can: set init flag earlier in probe Marc Kleine-Budde
@ 2024-12-19  2:00   ` patchwork-bot+netdevbpf
  0 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-12-19  2:00 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: netdev, davem, kuba, linux-can, kernel, matthias.schiffer, msp

Hello:

This series was applied to netdev/net.git (main)
by Marc Kleine-Budde <mkl@pengutronix.de>:

On Wed, 18 Dec 2024 13:10:27 +0100 you wrote:
> From: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
> 
> While an m_can controller usually already has the init flag from a
> hardware reset, no such reset happens on the integrated m_can_pci of the
> Intel Elkhart Lake. If the CAN controller is found in an active state,
> m_can_dev_setup() would fail because m_can_niso_supported() calls
> m_can_cccr_update_bits(), which refuses to modify any other configuration
> bits when CCCR_INIT is not set.
> 
> [...]

Here is the summary with links:
  - [net,1/2] can: m_can: set init flag earlier in probe
    https://git.kernel.org/netdev/net/c/fca2977629f4
  - [net,2/2] can: m_can: fix missed interrupts with m_can_pci
    https://git.kernel.org/netdev/net/c/743375f8deee

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 0/2] pull-request: can 2024-12-18
  2024-12-19  1:54 ` [PATCH net 0/2] pull-request: can 2024-12-18 Jakub Kicinski
@ 2024-12-19  8:03   ` Marc Kleine-Budde
  0 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2024-12-19  8:03 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, davem, linux-can, kernel

[-- Attachment #1: Type: text/plain, Size: 561 bytes --]

On 18.12.2024 17:54:23, Jakub Kicinski wrote:
> On Wed, 18 Dec 2024 13:10:26 +0100 Marc Kleine-Budde wrote:
> > this is a pull request of 21 patches for net/master.
> 
> The "21" is just quantum state of 1 becoming 2? ;)

Must have been the infamous fat-finger quantum state :)

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-12-19  8:03 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-18 12:10 [PATCH net 0/2] pull-request: can 2024-12-18 Marc Kleine-Budde
2024-12-18 12:10 ` [PATCH net 1/2] can: m_can: set init flag earlier in probe Marc Kleine-Budde
2024-12-19  2:00   ` patchwork-bot+netdevbpf
2024-12-18 12:10 ` [PATCH net 2/2] can: m_can: fix missed interrupts with m_can_pci Marc Kleine-Budde
2024-12-19  1:51   ` Jakub Kicinski
2024-12-19  1:54 ` [PATCH net 0/2] pull-request: can 2024-12-18 Jakub Kicinski
2024-12-19  8:03   ` Marc Kleine-Budde

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).