Skip to content

Commit 646f496

Browse files
committed
Merge tag 'linux-can-fixes-for-6.11-20240830' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can
Marc Kleine-Budde says: ==================== pull-request: can 2024-08-30 The first patch is by Kuniyuki Iwashima for the CAN BCM protocol that adds a missing proc entry removal when a device unregistered. Simon Horman fixes the cleanup in the error cleanup path of the m_can driver's open function. Markus Schneider-Pargmann contributes 7 fixes for the m_can driver, all related to the recently added IRQ coalescing support. The next 2 patches are by me, target the mcp251xfd driver and fix ring and coalescing configuration problems when switching from CAN-CC to CAN-FD mode. Simon Arlott's patch fixes a possible deadlock in the mcp251x driver. The last patch is by Martin Jocic for the kvaser_pciefd driver and fixes a problem with lost IRQs, which result in starvation, under high load situations. * tag 'linux-can-fixes-for-6.11-20240830' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: kvaser_pciefd: Use a single write when releasing RX buffers can: mcp251x: fix deadlock if an interrupt occurs during mcp251x_open can: mcp251xfd: mcp251xfd_ring_init(): check TX-coalescing configuration can: mcp251xfd: fix ring configuration when switching from CAN-CC to CAN-FD mode can: m_can: Limit coalescing to peripheral instances can: m_can: Reset cached active_interrupts on start can: m_can: disable_all_interrupts, not clear active_interrupts can: m_can: Do not cancel timer from within timer can: m_can: Remove m_can_rx_peripheral indirection can: m_can: Remove coalesing disable in isr during suspend can: m_can: Reset coalescing during suspend/resume can: m_can: Release irq on error in m_can_open can: bcm: Remove proc entry when dev is unregistered. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents ef4a99a + dd885d9 commit 646f496

File tree

6 files changed

+121
-64
lines changed

6 files changed

+121
-64
lines changed

drivers/net/can/kvaser_pciefd.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
16861686
const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask;
16871687
u32 pci_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
16881688
u32 srb_irq = 0;
1689+
u32 srb_release = 0;
16891690
int i;
16901691

16911692
if (!(pci_irq & irq_mask->all))
@@ -1699,17 +1700,14 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
16991700
kvaser_pciefd_transmit_irq(pcie->can[i]);
17001701
}
17011702

1702-
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
1703-
/* Reset DMA buffer 0, may trigger new interrupt */
1704-
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
1705-
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
1706-
}
1703+
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD0)
1704+
srb_release |= KVASER_PCIEFD_SRB_CMD_RDB0;
17071705

1708-
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
1709-
/* Reset DMA buffer 1, may trigger new interrupt */
1710-
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
1711-
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
1712-
}
1706+
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD1)
1707+
srb_release |= KVASER_PCIEFD_SRB_CMD_RDB1;
1708+
1709+
if (srb_release)
1710+
iowrite32(srb_release, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
17131711

17141712
return IRQ_HANDLED;
17151713
}

drivers/net/can/m_can/m_can.c

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,10 @@ static inline void m_can_disable_all_interrupts(struct m_can_classdev *cdev)
483483
{
484484
m_can_coalescing_disable(cdev);
485485
m_can_write(cdev, M_CAN_ILE, 0x0);
486-
cdev->active_interrupts = 0x0;
487486

488487
if (!cdev->net->irq) {
489488
dev_dbg(cdev->dev, "Stop hrtimer\n");
490-
hrtimer_cancel(&cdev->hrtimer);
489+
hrtimer_try_to_cancel(&cdev->hrtimer);
491490
}
492491
}
493492

@@ -1037,22 +1036,6 @@ static int m_can_rx_handler(struct net_device *dev, int quota, u32 irqstatus)
10371036
return work_done;
10381037
}
10391038

1040-
static int m_can_rx_peripheral(struct net_device *dev, u32 irqstatus)
1041-
{
1042-
struct m_can_classdev *cdev = netdev_priv(dev);
1043-
int work_done;
1044-
1045-
work_done = m_can_rx_handler(dev, NAPI_POLL_WEIGHT, irqstatus);
1046-
1047-
/* Don't re-enable interrupts if the driver had a fatal error
1048-
* (e.g., FIFO read failure).
1049-
*/
1050-
if (work_done < 0)
1051-
m_can_disable_all_interrupts(cdev);
1052-
1053-
return work_done;
1054-
}
1055-
10561039
static int m_can_poll(struct napi_struct *napi, int quota)
10571040
{
10581041
struct net_device *dev = napi->dev;
@@ -1217,16 +1200,18 @@ static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir)
12171200
HRTIMER_MODE_REL);
12181201
}
12191202

1220-
static irqreturn_t m_can_isr(int irq, void *dev_id)
1203+
/* This interrupt handler is called either from the interrupt thread or a
1204+
* hrtimer. This has implications like cancelling a timer won't be possible
1205+
* blocking.
1206+
*/
1207+
static int m_can_interrupt_handler(struct m_can_classdev *cdev)
12211208
{
1222-
struct net_device *dev = (struct net_device *)dev_id;
1223-
struct m_can_classdev *cdev = netdev_priv(dev);
1209+
struct net_device *dev = cdev->net;
12241210
u32 ir;
1211+
int ret;
12251212

1226-
if (pm_runtime_suspended(cdev->dev)) {
1227-
m_can_coalescing_disable(cdev);
1213+
if (pm_runtime_suspended(cdev->dev))
12281214
return IRQ_NONE;
1229-
}
12301215

12311216
ir = m_can_read(cdev, M_CAN_IR);
12321217
m_can_coalescing_update(cdev, ir);
@@ -1250,11 +1235,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
12501235
m_can_disable_all_interrupts(cdev);
12511236
napi_schedule(&cdev->napi);
12521237
} else {
1253-
int pkts;
1254-
1255-
pkts = m_can_rx_peripheral(dev, ir);
1256-
if (pkts < 0)
1257-
goto out_fail;
1238+
ret = m_can_rx_handler(dev, NAPI_POLL_WEIGHT, ir);
1239+
if (ret < 0)
1240+
return ret;
12581241
}
12591242
}
12601243

@@ -1272,25 +1255,41 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
12721255
} else {
12731256
if (ir & (IR_TEFN | IR_TEFW)) {
12741257
/* New TX FIFO Element arrived */
1275-
if (m_can_echo_tx_event(dev) != 0)
1276-
goto out_fail;
1258+
ret = m_can_echo_tx_event(dev);
1259+
if (ret != 0)
1260+
return ret;
12771261
}
12781262
}
12791263

12801264
if (cdev->is_peripheral)
12811265
can_rx_offload_threaded_irq_finish(&cdev->offload);
12821266

12831267
return IRQ_HANDLED;
1268+
}
12841269

1285-
out_fail:
1286-
m_can_disable_all_interrupts(cdev);
1287-
return IRQ_HANDLED;
1270+
static irqreturn_t m_can_isr(int irq, void *dev_id)
1271+
{
1272+
struct net_device *dev = (struct net_device *)dev_id;
1273+
struct m_can_classdev *cdev = netdev_priv(dev);
1274+
int ret;
1275+
1276+
ret = m_can_interrupt_handler(cdev);
1277+
if (ret < 0) {
1278+
m_can_disable_all_interrupts(cdev);
1279+
return IRQ_HANDLED;
1280+
}
1281+
1282+
return ret;
12881283
}
12891284

12901285
static enum hrtimer_restart m_can_coalescing_timer(struct hrtimer *timer)
12911286
{
12921287
struct m_can_classdev *cdev = container_of(timer, struct m_can_classdev, hrtimer);
12931288

1289+
if (cdev->can.state == CAN_STATE_BUS_OFF ||
1290+
cdev->can.state == CAN_STATE_STOPPED)
1291+
return HRTIMER_NORESTART;
1292+
12941293
irq_wake_thread(cdev->net->irq, cdev->net);
12951294

12961295
return HRTIMER_NORESTART;
@@ -1542,6 +1541,7 @@ static int m_can_chip_config(struct net_device *dev)
15421541
else
15431542
interrupts &= ~(IR_ERR_LEC_31X);
15441543
}
1544+
cdev->active_interrupts = 0;
15451545
m_can_interrupt_enable(cdev, interrupts);
15461546

15471547
/* route all interrupts to INT0 */
@@ -1991,8 +1991,17 @@ static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
19911991
{
19921992
struct m_can_classdev *cdev = container_of(timer, struct
19931993
m_can_classdev, hrtimer);
1994+
int ret;
1995+
1996+
if (cdev->can.state == CAN_STATE_BUS_OFF ||
1997+
cdev->can.state == CAN_STATE_STOPPED)
1998+
return HRTIMER_NORESTART;
19941999

1995-
m_can_isr(0, cdev->net);
2000+
ret = m_can_interrupt_handler(cdev);
2001+
2002+
/* On error or if napi is scheduled to read, stop the timer */
2003+
if (ret < 0 || napi_is_scheduled(&cdev->napi))
2004+
return HRTIMER_NORESTART;
19962005

19972006
hrtimer_forward_now(timer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS));
19982007

@@ -2052,7 +2061,7 @@ static int m_can_open(struct net_device *dev)
20522061
/* start the m_can controller */
20532062
err = m_can_start(dev);
20542063
if (err)
2055-
goto exit_irq_fail;
2064+
goto exit_start_fail;
20562065

20572066
if (!cdev->is_peripheral)
20582067
napi_enable(&cdev->napi);
@@ -2061,6 +2070,9 @@ static int m_can_open(struct net_device *dev)
20612070

20622071
return 0;
20632072

2073+
exit_start_fail:
2074+
if (cdev->is_peripheral || dev->irq)
2075+
free_irq(dev->irq, dev);
20642076
exit_irq_fail:
20652077
if (cdev->is_peripheral)
20662078
destroy_workqueue(cdev->tx_wq);
@@ -2172,7 +2184,7 @@ static int m_can_set_coalesce(struct net_device *dev,
21722184
return 0;
21732185
}
21742186

2175-
static const struct ethtool_ops m_can_ethtool_ops = {
2187+
static const struct ethtool_ops m_can_ethtool_ops_coalescing = {
21762188
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
21772189
ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |
21782190
ETHTOOL_COALESCE_TX_USECS_IRQ |
@@ -2183,18 +2195,20 @@ static const struct ethtool_ops m_can_ethtool_ops = {
21832195
.set_coalesce = m_can_set_coalesce,
21842196
};
21852197

2186-
static const struct ethtool_ops m_can_ethtool_ops_polling = {
2198+
static const struct ethtool_ops m_can_ethtool_ops = {
21872199
.get_ts_info = ethtool_op_get_ts_info,
21882200
};
21892201

2190-
static int register_m_can_dev(struct net_device *dev)
2202+
static int register_m_can_dev(struct m_can_classdev *cdev)
21912203
{
2204+
struct net_device *dev = cdev->net;
2205+
21922206
dev->flags |= IFF_ECHO; /* we support local echo */
21932207
dev->netdev_ops = &m_can_netdev_ops;
2194-
if (dev->irq)
2195-
dev->ethtool_ops = &m_can_ethtool_ops;
2208+
if (dev->irq && cdev->is_peripheral)
2209+
dev->ethtool_ops = &m_can_ethtool_ops_coalescing;
21962210
else
2197-
dev->ethtool_ops = &m_can_ethtool_ops_polling;
2211+
dev->ethtool_ops = &m_can_ethtool_ops;
21982212

21992213
return register_candev(dev);
22002214
}
@@ -2380,7 +2394,7 @@ int m_can_class_register(struct m_can_classdev *cdev)
23802394
if (ret)
23812395
goto rx_offload_del;
23822396

2383-
ret = register_m_can_dev(cdev->net);
2397+
ret = register_m_can_dev(cdev);
23842398
if (ret) {
23852399
dev_err(cdev->dev, "registering %s failed (err=%d)\n",
23862400
cdev->net->name, ret);
@@ -2427,12 +2441,15 @@ int m_can_class_suspend(struct device *dev)
24272441
netif_device_detach(ndev);
24282442

24292443
/* leave the chip running with rx interrupt enabled if it is
2430-
* used as a wake-up source.
2444+
* used as a wake-up source. Coalescing needs to be reset then,
2445+
* the timer is cancelled here, interrupts are done in resume.
24312446
*/
2432-
if (cdev->pm_wake_source)
2447+
if (cdev->pm_wake_source) {
2448+
hrtimer_cancel(&cdev->hrtimer);
24332449
m_can_write(cdev, M_CAN_IE, IR_RF0N);
2434-
else
2450+
} else {
24352451
m_can_stop(ndev);
2452+
}
24362453

24372454
m_can_clk_stop(cdev);
24382455
}
@@ -2462,6 +2479,13 @@ int m_can_class_resume(struct device *dev)
24622479
return ret;
24632480

24642481
if (cdev->pm_wake_source) {
2482+
/* Restore active interrupts but disable coalescing as
2483+
* we may have missed important waterlevel interrupts
2484+
* between suspend and resume. Timers are already
2485+
* stopped in suspend. Here we enable all interrupts
2486+
* again.
2487+
*/
2488+
cdev->active_interrupts |= IR_RF0N | IR_TEFN;
24652489
m_can_write(cdev, M_CAN_IE, cdev->active_interrupts);
24662490
} else {
24672491
ret = m_can_start(ndev);

drivers/net/can/spi/mcp251x.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ static int mcp251x_hw_wake(struct spi_device *spi)
752752
int ret;
753753

754754
/* Force wakeup interrupt to wake device, but don't execute IST */
755-
disable_irq(spi->irq);
755+
disable_irq_nosync(spi->irq);
756756
mcp251x_write_2regs(spi, CANINTE, CANINTE_WAKIE, CANINTF_WAKIF);
757757

758758
/* Wait for oscillator startup timer after wake up */

drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,16 @@ void can_ram_get_layout(struct can_ram_layout *layout,
9797
if (ring) {
9898
u8 num_rx_coalesce = 0, num_tx_coalesce = 0;
9999

100-
num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, ring->rx_pending);
100+
/* If the ring parameters have been configured in
101+
* CAN-CC mode, but and we are in CAN-FD mode now,
102+
* they might be to big. Use the default CAN-FD values
103+
* in this case.
104+
*/
105+
num_rx = ring->rx_pending;
106+
if (num_rx > layout->max_rx)
107+
num_rx = layout->default_rx;
108+
109+
num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
101110

102111
/* The ethtool doc says:
103112
* To disable coalescing, set usecs = 0 and max_frames = 1.

drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
290290
const struct mcp251xfd_rx_ring *rx_ring;
291291
u16 base = 0, ram_used;
292292
u8 fifo_nr = 1;
293-
int i;
293+
int err = 0, i;
294294

295295
netdev_reset_queue(priv->ndev);
296296

@@ -386,10 +386,18 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
386386
netdev_err(priv->ndev,
387387
"Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
388388
ram_used, MCP251XFD_RAM_SIZE);
389-
return -ENOMEM;
389+
err = -ENOMEM;
390390
}
391391

392-
return 0;
392+
if (priv->tx_obj_num_coalesce_irq &&
393+
priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
394+
netdev_err(priv->ndev,
395+
"Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
396+
priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
397+
err = -EINVAL;
398+
}
399+
400+
return err;
393401
}
394402

395403
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
@@ -469,11 +477,25 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
469477

470478
/* switching from CAN-2.0 to CAN-FD mode or vice versa */
471479
if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
480+
const struct ethtool_ringparam ring = {
481+
.rx_pending = priv->rx_obj_num,
482+
.tx_pending = priv->tx->obj_num,
483+
};
484+
const struct ethtool_coalesce ec = {
485+
.rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq,
486+
.rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq,
487+
.tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq,
488+
.tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq,
489+
};
472490
struct can_ram_layout layout;
473491

474-
can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
475-
priv->rx_obj_num = layout.default_rx;
476-
tx_ring->obj_num = layout.default_tx;
492+
can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, &ec, fd_mode);
493+
494+
priv->rx_obj_num = layout.cur_rx;
495+
priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
496+
497+
tx_ring->obj_num = layout.cur_tx;
498+
priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
477499
}
478500

479501
if (fd_mode) {

net/can/bcm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,10 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
14701470

14711471
/* remove device reference, if this is our bound device */
14721472
if (bo->bound && bo->ifindex == dev->ifindex) {
1473+
#if IS_ENABLED(CONFIG_PROC_FS)
1474+
if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read)
1475+
remove_proc_entry(bo->procname, sock_net(sk)->can.bcmproc_dir);
1476+
#endif
14731477
bo->bound = 0;
14741478
bo->ifindex = 0;
14751479
notify_enodev = 1;

0 commit comments

Comments
 (0)