linux-can-fixes-for-6.13-20241218
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEUEC6huC2BN0pvD5fKDiiPnotvG8FAmdiu2ATHG1rbEBwZW5n dXRyb25peC5kZQAKCRAoOKI+ei28b5YcB/9FJzf46miwv8ehTOi1F27YoYcwNrmu r0rypJorQvm3cUWtl501tCKD1bw3JUdhbqb72w8/Y2gUNEdyk5RnhacVuh6fJI5+ mYOK+1r5yOqodzagQyM9r4Cn0xyLO1A7Gtddjbh1FUCjNQNXtGVgI5Vamyq1tb5i SbfOKigvYqDGY0DTb1HemYPrGmQYojrQcvw0s2ZqV5ySy2EY5o+9LqEQkD7yPMly nT1fM5ruJyxmnMSYco+UskzNqoR/yyWrNhCWMns0+M5PVVDdtdd8qr5xlFO5vnp4 ECLgfK8ZkDCC5PblL5sb3u4hc3/RqpfZhaH4jkvLqMA+gaMlE58viMtd =YVbz -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-6.13-20241218' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2024-12-18 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. * tag 'linux-can-fixes-for-6.13-20241218' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: m_can: fix missed interrupts with m_can_pci can: m_can: set init flag earlier in probe ==================== Link: https://patch.msgid.link/20241218121722.2311963-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
dbfca1641e
|
|
@ -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);
|
||||
|
||||
|
|
@ -1695,6 +1707,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 +1766,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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue