Skip to content

Commit b353b24

Browse files
Csókás Bencekuba-moo
authored andcommitted
net: fec: Use a spinlock to guard fep->ptp_clk_on
Mutexes cannot be taken in a non-preemptible context, causing a panic in `fec_ptp_save_state()`. Replacing `ptp_clk_mutex` by `tmreg_lock` fixes this. Fixes: 6a4d723 ("net: fec: ptp: avoid register access when ipg clock is disabled") Fixes: f799592 ("fec: Restart PPS after link state change") Reported-by: Marc Kleine-Budde <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Csókás Bence <[email protected]> Tested-by: Francesco Dolcini <[email protected]> # Toradex Apalis iMX6 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7d650df commit b353b24

File tree

3 files changed

+19
-27
lines changed

3 files changed

+19
-27
lines changed

drivers/net/ethernet/freescale/fec.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,6 @@ struct fec_enet_private {
561561
struct clk *clk_2x_txclk;
562562

563563
bool ptp_clk_on;
564-
struct mutex ptp_clk_mutex;
565564
unsigned int num_tx_queues;
566565
unsigned int num_rx_queues;
567566

drivers/net/ethernet/freescale/fec_main.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,6 +2029,7 @@ static void fec_enet_phy_reset_after_clk_enable(struct net_device *ndev)
20292029
static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
20302030
{
20312031
struct fec_enet_private *fep = netdev_priv(ndev);
2032+
unsigned long flags;
20322033
int ret;
20332034

20342035
if (enable) {
@@ -2037,15 +2038,15 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
20372038
return ret;
20382039

20392040
if (fep->clk_ptp) {
2040-
mutex_lock(&fep->ptp_clk_mutex);
2041+
spin_lock_irqsave(&fep->tmreg_lock, flags);
20412042
ret = clk_prepare_enable(fep->clk_ptp);
20422043
if (ret) {
2043-
mutex_unlock(&fep->ptp_clk_mutex);
2044+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
20442045
goto failed_clk_ptp;
20452046
} else {
20462047
fep->ptp_clk_on = true;
20472048
}
2048-
mutex_unlock(&fep->ptp_clk_mutex);
2049+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
20492050
}
20502051

20512052
ret = clk_prepare_enable(fep->clk_ref);
@@ -2060,10 +2061,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
20602061
} else {
20612062
clk_disable_unprepare(fep->clk_enet_out);
20622063
if (fep->clk_ptp) {
2063-
mutex_lock(&fep->ptp_clk_mutex);
2064+
spin_lock_irqsave(&fep->tmreg_lock, flags);
20642065
clk_disable_unprepare(fep->clk_ptp);
20652066
fep->ptp_clk_on = false;
2066-
mutex_unlock(&fep->ptp_clk_mutex);
2067+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
20672068
}
20682069
clk_disable_unprepare(fep->clk_ref);
20692070
clk_disable_unprepare(fep->clk_2x_txclk);
@@ -2076,10 +2077,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
20762077
clk_disable_unprepare(fep->clk_ref);
20772078
failed_clk_ref:
20782079
if (fep->clk_ptp) {
2079-
mutex_lock(&fep->ptp_clk_mutex);
2080+
spin_lock_irqsave(&fep->tmreg_lock, flags);
20802081
clk_disable_unprepare(fep->clk_ptp);
20812082
fep->ptp_clk_on = false;
2082-
mutex_unlock(&fep->ptp_clk_mutex);
2083+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
20832084
}
20842085
failed_clk_ptp:
20852086
clk_disable_unprepare(fep->clk_enet_out);
@@ -3914,7 +3915,7 @@ fec_probe(struct platform_device *pdev)
39143915
}
39153916

39163917
fep->ptp_clk_on = false;
3917-
mutex_init(&fep->ptp_clk_mutex);
3918+
spin_lock_init(&fep->tmreg_lock);
39183919

39193920
/* clk_ref is optional, depends on board */
39203921
fep->clk_ref = devm_clk_get_optional(&pdev->dev, "enet_clk_ref");

drivers/net/ethernet/freescale/fec_ptp.c

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -365,21 +365,19 @@ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
365365
*/
366366
static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
367367
{
368-
struct fec_enet_private *adapter =
368+
struct fec_enet_private *fep =
369369
container_of(ptp, struct fec_enet_private, ptp_caps);
370370
u64 ns;
371371
unsigned long flags;
372372

373-
mutex_lock(&adapter->ptp_clk_mutex);
373+
spin_lock_irqsave(&fep->tmreg_lock, flags);
374374
/* Check the ptp clock */
375-
if (!adapter->ptp_clk_on) {
376-
mutex_unlock(&adapter->ptp_clk_mutex);
375+
if (!fep->ptp_clk_on) {
376+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
377377
return -EINVAL;
378378
}
379-
spin_lock_irqsave(&adapter->tmreg_lock, flags);
380-
ns = timecounter_read(&adapter->tc);
381-
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
382-
mutex_unlock(&adapter->ptp_clk_mutex);
379+
ns = timecounter_read(&fep->tc);
380+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
383381

384382
*ts = ns_to_timespec64(ns);
385383

@@ -404,10 +402,10 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
404402
unsigned long flags;
405403
u32 counter;
406404

407-
mutex_lock(&fep->ptp_clk_mutex);
405+
spin_lock_irqsave(&fep->tmreg_lock, flags);
408406
/* Check the ptp clock */
409407
if (!fep->ptp_clk_on) {
410-
mutex_unlock(&fep->ptp_clk_mutex);
408+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
411409
return -EINVAL;
412410
}
413411

@@ -417,11 +415,9 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
417415
*/
418416
counter = ns & fep->cc.mask;
419417

420-
spin_lock_irqsave(&fep->tmreg_lock, flags);
421418
writel(counter, fep->hwp + FEC_ATIME);
422419
timecounter_init(&fep->tc, &fep->cc, ns);
423420
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
424-
mutex_unlock(&fep->ptp_clk_mutex);
425421
return 0;
426422
}
427423

@@ -518,13 +514,11 @@ static void fec_time_keep(struct work_struct *work)
518514
struct fec_enet_private *fep = container_of(dwork, struct fec_enet_private, time_keep);
519515
unsigned long flags;
520516

521-
mutex_lock(&fep->ptp_clk_mutex);
517+
spin_lock_irqsave(&fep->tmreg_lock, flags);
522518
if (fep->ptp_clk_on) {
523-
spin_lock_irqsave(&fep->tmreg_lock, flags);
524519
timecounter_read(&fep->tc);
525-
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
526520
}
527-
mutex_unlock(&fep->ptp_clk_mutex);
521+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
528522

529523
schedule_delayed_work(&fep->time_keep, HZ);
530524
}
@@ -599,8 +593,6 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
599593
}
600594
fep->ptp_inc = NSEC_PER_SEC / fep->cycle_speed;
601595

602-
spin_lock_init(&fep->tmreg_lock);
603-
604596
fec_ptp_start_cyclecounter(ndev);
605597

606598
INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep);

0 commit comments

Comments
 (0)