Skip to content

Commit 053ae05

Browse files
Merge patch series "can: m_can: Fix polling and other issues"
Markus Schneider-Pargmann <msp@baylibre.com> says: these are a number of fixes for m_can that fix polling mode and some other issues that I saw while working on the code. Changes in v2 ------------- - Fixed one multiline comment - Rebased to v6.11-rc1 Previous versions ----------------- v1: https://lore.kernel.org/lkml/20240726195944.2414812-1-msp@baylibre.com/ Link: https://lore.kernel.org/all/20240805183047.305630-1-msp@baylibre.com Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2 parents 06d4ef3 + e443d15 commit 053ae05

1 file changed

Lines changed: 66 additions & 45 deletions

File tree

drivers/net/can/m_can/m_can.c

Lines changed: 66 additions & 45 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;
19941995

1995-
m_can_isr(0, cdev->net);
1996+
if (cdev->can.state == CAN_STATE_BUS_OFF ||
1997+
cdev->can.state == CAN_STATE_STOPPED)
1998+
return HRTIMER_NORESTART;
1999+
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

@@ -2175,7 +2184,7 @@ static int m_can_set_coalesce(struct net_device *dev,
21752184
return 0;
21762185
}
21772186

2178-
static const struct ethtool_ops m_can_ethtool_ops = {
2187+
static const struct ethtool_ops m_can_ethtool_ops_coalescing = {
21792188
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
21802189
ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |
21812190
ETHTOOL_COALESCE_TX_USECS_IRQ |
@@ -2186,18 +2195,20 @@ static const struct ethtool_ops m_can_ethtool_ops = {
21862195
.set_coalesce = m_can_set_coalesce,
21872196
};
21882197

2189-
static const struct ethtool_ops m_can_ethtool_ops_polling = {
2198+
static const struct ethtool_ops m_can_ethtool_ops = {
21902199
.get_ts_info = ethtool_op_get_ts_info,
21912200
};
21922201

2193-
static int register_m_can_dev(struct net_device *dev)
2202+
static int register_m_can_dev(struct m_can_classdev *cdev)
21942203
{
2204+
struct net_device *dev = cdev->net;
2205+
21952206
dev->flags |= IFF_ECHO; /* we support local echo */
21962207
dev->netdev_ops = &m_can_netdev_ops;
2197-
if (dev->irq)
2198-
dev->ethtool_ops = &m_can_ethtool_ops;
2208+
if (dev->irq && cdev->is_peripheral)
2209+
dev->ethtool_ops = &m_can_ethtool_ops_coalescing;
21992210
else
2200-
dev->ethtool_ops = &m_can_ethtool_ops_polling;
2211+
dev->ethtool_ops = &m_can_ethtool_ops;
22012212

22022213
return register_candev(dev);
22032214
}
@@ -2383,7 +2394,7 @@ int m_can_class_register(struct m_can_classdev *cdev)
23832394
if (ret)
23842395
goto rx_offload_del;
23852396

2386-
ret = register_m_can_dev(cdev->net);
2397+
ret = register_m_can_dev(cdev);
23872398
if (ret) {
23882399
dev_err(cdev->dev, "registering %s failed (err=%d)\n",
23892400
cdev->net->name, ret);
@@ -2430,12 +2441,15 @@ int m_can_class_suspend(struct device *dev)
24302441
netif_device_detach(ndev);
24312442

24322443
/* leave the chip running with rx interrupt enabled if it is
2433-
* 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.
24342446
*/
2435-
if (cdev->pm_wake_source)
2447+
if (cdev->pm_wake_source) {
2448+
hrtimer_cancel(&cdev->hrtimer);
24362449
m_can_write(cdev, M_CAN_IE, IR_RF0N);
2437-
else
2450+
} else {
24382451
m_can_stop(ndev);
2452+
}
24392453

24402454
m_can_clk_stop(cdev);
24412455
}
@@ -2465,6 +2479,13 @@ int m_can_class_resume(struct device *dev)
24652479
return ret;
24662480

24672481
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;
24682489
m_can_write(cdev, M_CAN_IE, cdev->active_interrupts);
24692490
} else {
24702491
ret = m_can_start(ndev);

0 commit comments

Comments
 (0)