* [PATCH 6.1.y 2/7] net: ravb: Switch to SYSTEM_SLEEP_PM_OPS()/RUNTIME_PM_OPS() and pm_ptr()
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 3/7] net: ravb: Move reference clock enable/disable on runtime PM APIs Sasha Levin
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable
Cc: Claudiu Beznea, Sergey Shtylyov, Geert Uytterhoeven, Paolo Abeni,
Sasha Levin
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
[ Upstream commit 6ccc22a5afcbac46d55866d72eaba22f43491c00 ]
SET_SYSTEM_SLEEP_PM_OPS() and SET_RUNTIME_PM_OPS() are deprecated now
and require __maybe_unused protection against unused function warnings.
The usage of pm_ptr() and SYSTEM_SLEEP_PM_OPS()/RUNTIME_PM_OPS() allows
the compiler to see the functions, thus suppressing the warning. Thus
drop the __maybe_unused markings.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 1cb9663789c5 ("net: ravb: serialize PTP clock teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb_main.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index bc893fd6eb023..13095421f1e24 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -3012,7 +3012,7 @@ static int ravb_wol_restore(struct net_device *ndev)
return disable_irq_wake(priv->emac_irq);
}
-static int __maybe_unused ravb_suspend(struct device *dev)
+static int ravb_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct ravb_private *priv = netdev_priv(ndev);
@@ -3034,7 +3034,7 @@ static int __maybe_unused ravb_suspend(struct device *dev)
return ret;
}
-static int __maybe_unused ravb_resume(struct device *dev)
+static int ravb_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct ravb_private *priv = netdev_priv(ndev);
@@ -3093,7 +3093,7 @@ static int __maybe_unused ravb_resume(struct device *dev)
return ret;
}
-static int __maybe_unused ravb_runtime_nop(struct device *dev)
+static int ravb_runtime_nop(struct device *dev)
{
/* Runtime PM callback shared between ->runtime_suspend()
* and ->runtime_resume(). Simply returns success.
@@ -3106,8 +3106,8 @@ static int __maybe_unused ravb_runtime_nop(struct device *dev)
}
static const struct dev_pm_ops ravb_dev_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume)
- SET_RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL)
+ SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume)
+ RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL)
};
static struct platform_driver ravb_driver = {
@@ -3115,7 +3115,7 @@ static struct platform_driver ravb_driver = {
.remove = ravb_remove,
.driver = {
.name = "ravb",
- .pm = &ravb_dev_pm_ops,
+ .pm = pm_ptr(&ravb_dev_pm_ops),
.of_match_table = ravb_match_table,
},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6.1.y 3/7] net: ravb: Move reference clock enable/disable on runtime PM APIs
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 2/7] net: ravb: Switch to SYSTEM_SLEEP_PM_OPS()/RUNTIME_PM_OPS() and pm_ptr() Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 4/7] net: ravb: Move getting/requesting IRQs in the probe() method Sasha Levin
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable; +Cc: Claudiu Beznea, Sergey Shtylyov, Paolo Abeni, Sasha Levin
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
[ Upstream commit a654f6e875b753d11643840e266f7fd75e5ee1fa ]
Reference clock could be or not be part of the power domain. If it is part
of the power domain, the power domain takes care of properly setting it. In
case it is not part of the power domain and full runtime PM support is
available in driver the clock will not be propertly disabled/enabled at
runtime. For this, keep the prepare/unprepare operations in the driver's
probe()/remove() functions and move the enable/disable in runtime PM
functions.
By doing this, the previous ravb_runtime_nop() function was renamed
ravb_runtime_suspend() and the comment was removed. A proper runtime PM
resume function was added (ravb_runtime_resume()). The current driver
still don't need to make any register settings on runtime suspend/resume
(as expressed in the removed comment) because, currently,
pm_runtime_put_sync() is called on the driver remove function. This will be
changed in the next commits (that extends the runtime PM support) such
that proper register settings (along with runtime resume/suspend) will be
done on ravb_open()/ravb_close().
Along with it, the other clock request operations were moved close to
reference clock request and prepare to have all the clock requests
specific code grouped together.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 1cb9663789c5 ("net: ravb: serialize PTP clock teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb_main.c | 110 ++++++++++++-----------
1 file changed, 57 insertions(+), 53 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 13095421f1e24..58507bd4075e8 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2703,11 +2703,6 @@ static int ravb_probe(struct platform_device *pdev)
if (error)
goto out_free_netdev;
- pm_runtime_enable(&pdev->dev);
- error = pm_runtime_resume_and_get(&pdev->dev);
- if (error < 0)
- goto out_rpm_disable;
-
if (info->multi_irqs) {
if (info->err_mgmt_irqs)
irq = platform_get_irq_byname(pdev, "dia");
@@ -2718,7 +2713,7 @@ static int ravb_probe(struct platform_device *pdev)
}
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_reset_assert;
}
ndev->irq = irq;
@@ -2736,10 +2731,37 @@ static int ravb_probe(struct platform_device *pdev)
priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE;
}
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ error = PTR_ERR(priv->clk);
+ goto out_reset_assert;
+ }
+
+ if (info->gptp_ref_clk) {
+ priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp");
+ if (IS_ERR(priv->gptp_clk)) {
+ error = PTR_ERR(priv->gptp_clk);
+ goto out_reset_assert;
+ }
+ }
+
+ priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk");
+ if (IS_ERR(priv->refclk)) {
+ error = PTR_ERR(priv->refclk);
+ goto out_reset_assert;
+ }
+ clk_prepare(priv->refclk);
+
+ platform_set_drvdata(pdev, ndev);
+ pm_runtime_enable(&pdev->dev);
+ error = pm_runtime_resume_and_get(&pdev->dev);
+ if (error < 0)
+ goto out_rpm_disable;
+
priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(priv->addr)) {
error = PTR_ERR(priv->addr);
- goto out_release;
+ goto out_rpm_put;
}
/* The Ether-specific entries in the device structure. */
@@ -2750,7 +2772,7 @@ static int ravb_probe(struct platform_device *pdev)
error = of_get_phy_mode(np, &priv->phy_interface);
if (error && error != -ENODEV)
- goto out_release;
+ goto out_rpm_put;
priv->no_avb_link = of_property_read_bool(np, "renesas,no-ether-link");
priv->avb_link_active_low =
@@ -2763,14 +2785,14 @@ static int ravb_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, "ch24");
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_rpm_put;
}
priv->emac_irq = irq;
for (i = 0; i < NUM_RX_QUEUE; i++) {
irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]);
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_rpm_put;
}
priv->rx_irqs[i] = irq;
}
@@ -2778,7 +2800,7 @@ static int ravb_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]);
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_rpm_put;
}
priv->tx_irqs[i] = irq;
}
@@ -2787,40 +2809,19 @@ static int ravb_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, "err_a");
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_rpm_put;
}
priv->erra_irq = irq;
irq = platform_get_irq_byname(pdev, "mgmt_a");
if (irq < 0) {
error = irq;
- goto out_release;
+ goto out_rpm_put;
}
priv->mgmta_irq = irq;
}
}
- priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(priv->clk)) {
- error = PTR_ERR(priv->clk);
- goto out_release;
- }
-
- priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk");
- if (IS_ERR(priv->refclk)) {
- error = PTR_ERR(priv->refclk);
- goto out_release;
- }
- clk_prepare_enable(priv->refclk);
-
- if (info->gptp_ref_clk) {
- priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp");
- if (IS_ERR(priv->gptp_clk)) {
- error = PTR_ERR(priv->gptp_clk);
- goto out_disable_refclk;
- }
- }
-
ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
ndev->min_mtu = ETH_MIN_MTU;
@@ -2838,13 +2839,13 @@ static int ravb_probe(struct platform_device *pdev)
/* Set AVB config mode */
error = ravb_set_config_mode(ndev);
if (error)
- goto out_disable_refclk;
+ goto out_rpm_put;
if (info->gptp || info->ccc_gac) {
/* Set GTI value */
error = ravb_set_gti(ndev);
if (error)
- goto out_disable_refclk;
+ goto out_rpm_put;
/* Request GTI loading */
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
@@ -2864,7 +2865,7 @@ static int ravb_probe(struct platform_device *pdev)
"Cannot allocate desc base address table (size %d bytes)\n",
priv->desc_bat_size);
error = -ENOMEM;
- goto out_disable_refclk;
+ goto out_rpm_put;
}
for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++)
priv->desc_bat[q].die_dt = DT_EOS;
@@ -2910,8 +2911,6 @@ static int ravb_probe(struct platform_device *pdev)
netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n",
(u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
- platform_set_drvdata(pdev, ndev);
-
return 0;
out_napi_del:
@@ -2927,12 +2926,12 @@ static int ravb_probe(struct platform_device *pdev)
/* Stop PTP Clock driver */
if (info->ccc_gac)
ravb_ptp_stop(ndev);
-out_disable_refclk:
- clk_disable_unprepare(priv->refclk);
-out_release:
+out_rpm_put:
pm_runtime_put(&pdev->dev);
out_rpm_disable:
pm_runtime_disable(&pdev->dev);
+ clk_unprepare(priv->refclk);
+out_reset_assert:
reset_control_assert(rstc);
out_free_netdev:
free_netdev(ndev);
@@ -2961,10 +2960,9 @@ static int ravb_remove(struct platform_device *pdev)
ravb_set_opmode(ndev, CCC_OPC_RESET);
- clk_disable_unprepare(priv->refclk);
-
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ clk_unprepare(priv->refclk);
reset_control_assert(priv->rstc);
free_netdev(ndev);
platform_set_drvdata(pdev, NULL);
@@ -3093,21 +3091,27 @@ static int ravb_resume(struct device *dev)
return ret;
}
-static int ravb_runtime_nop(struct device *dev)
+static int ravb_runtime_suspend(struct device *dev)
{
- /* Runtime PM callback shared between ->runtime_suspend()
- * and ->runtime_resume(). Simply returns success.
- *
- * This driver re-initializes all registers after
- * pm_runtime_get_sync() anyway so there is no need
- * to save and restore registers here.
- */
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct ravb_private *priv = netdev_priv(ndev);
+
+ clk_disable(priv->refclk);
+
return 0;
}
+static int ravb_runtime_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct ravb_private *priv = netdev_priv(ndev);
+
+ return clk_enable(priv->refclk);
+}
+
static const struct dev_pm_ops ravb_dev_pm_ops = {
SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume)
- RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL)
+ RUNTIME_PM_OPS(ravb_runtime_suspend, ravb_runtime_resume, NULL)
};
static struct platform_driver ravb_driver = {
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6.1.y 4/7] net: ravb: Move getting/requesting IRQs in the probe() method
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 2/7] net: ravb: Switch to SYSTEM_SLEEP_PM_OPS()/RUNTIME_PM_OPS() and pm_ptr() Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 3/7] net: ravb: Move reference clock enable/disable on runtime PM APIs Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 5/7] net: ravb: Get rid of the temporary variable irq Sasha Levin
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable; +Cc: Claudiu Beznea, Sergey Shtylyov, Paolo Abeni, Sasha Levin
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
[ Upstream commit 32f012b8c01ca9fd26a28134cc2165ead93c22d0 ]
The runtime PM implementation will disable clocks at the end of
ravb_probe(). As some IP variants switch to reset mode as a result of
setting module standby through clock disable APIs, to implement runtime PM
the resource parsing and requesting are moved in the probe function and IP
settings are moved in the open function. This is done because at the end of
the probe some IP variants will switch anyway to reset mode and the
registers content is lost. Also keeping only register settings operations
in the ravb_open()/ravb_close() functions will make them faster.
Commit moves IRQ requests to ravb_probe() to have all the IRQs ready when
the interface is open. As now getting/requesting IRQs is done in a single
place there is no need to keep intermediary data (like ravb_rx_irqs[] and
ravb_tx_irqs[] arrays or IRQs in struct ravb_private).
In order to avoid accessing the IP registers while the IP is runtime
suspended (e.g. in the timeframe b/w the probe requests shared IRQs and
IP clocks are enabled) in the interrupt handlers were introduced
pm_runtime_active() checks. The device runtime PM usage counter has been
incremented to avoid disabling the device's clocks while the check is in
progress (if any).
This is a preparatory change to add runtime PM support for all IP variants.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 1cb9663789c5 ("net: ravb: serialize PTP clock teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb.h | 4 -
drivers/net/ethernet/renesas/ravb_main.c | 299 ++++++++++-------------
2 files changed, 130 insertions(+), 173 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index e0f8276cffedd..e3506888cca6e 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1089,10 +1089,6 @@ struct ravb_private {
int msg_enable;
int speed;
int emac_irq;
- int erra_irq;
- int mgmta_irq;
- int rx_irqs[NUM_RX_QUEUE];
- int tx_irqs[NUM_TX_QUEUE];
unsigned no_avb_link:1;
unsigned avb_link_active_low:1;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 58507bd4075e8..0da019d1a2fd5 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -40,16 +40,6 @@
NETIF_MSG_RX_ERR | \
NETIF_MSG_TX_ERR)
-static const char *ravb_rx_irqs[NUM_RX_QUEUE] = {
- "ch0", /* RAVB_BE */
- "ch1", /* RAVB_NC */
-};
-
-static const char *ravb_tx_irqs[NUM_TX_QUEUE] = {
- "ch18", /* RAVB_BE */
- "ch19", /* RAVB_NC */
-};
-
void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear,
u32 set)
{
@@ -1094,11 +1084,23 @@ static irqreturn_t ravb_emac_interrupt(int irq, void *dev_id)
{
struct net_device *ndev = dev_id;
struct ravb_private *priv = netdev_priv(ndev);
+ struct device *dev = &priv->pdev->dev;
+ irqreturn_t result = IRQ_HANDLED;
+
+ pm_runtime_get_noresume(dev);
+
+ if (unlikely(!pm_runtime_active(dev))) {
+ result = IRQ_NONE;
+ goto out_rpm_put;
+ }
spin_lock(&priv->lock);
ravb_emac_interrupt_unlocked(ndev);
spin_unlock(&priv->lock);
- return IRQ_HANDLED;
+
+out_rpm_put:
+ pm_runtime_put_noidle(dev);
+ return result;
}
/* Error interrupt handler */
@@ -1178,9 +1180,15 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
struct net_device *ndev = dev_id;
struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info;
+ struct device *dev = &priv->pdev->dev;
irqreturn_t result = IRQ_NONE;
u32 iss;
+ pm_runtime_get_noresume(dev);
+
+ if (unlikely(!pm_runtime_active(dev)))
+ goto out_rpm_put;
+
spin_lock(&priv->lock);
/* Get interrupt status */
iss = ravb_read(ndev, ISS);
@@ -1224,6 +1232,9 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
}
spin_unlock(&priv->lock);
+
+out_rpm_put:
+ pm_runtime_put_noidle(dev);
return result;
}
@@ -1232,9 +1243,15 @@ static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id)
{
struct net_device *ndev = dev_id;
struct ravb_private *priv = netdev_priv(ndev);
+ struct device *dev = &priv->pdev->dev;
irqreturn_t result = IRQ_NONE;
u32 iss;
+ pm_runtime_get_noresume(dev);
+
+ if (unlikely(!pm_runtime_active(dev)))
+ goto out_rpm_put;
+
spin_lock(&priv->lock);
/* Get interrupt status */
iss = ravb_read(ndev, ISS);
@@ -1256,6 +1273,9 @@ static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id)
}
spin_unlock(&priv->lock);
+
+out_rpm_put:
+ pm_runtime_put_noidle(dev);
return result;
}
@@ -1263,8 +1283,14 @@ static irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q)
{
struct net_device *ndev = dev_id;
struct ravb_private *priv = netdev_priv(ndev);
+ struct device *dev = &priv->pdev->dev;
irqreturn_t result = IRQ_NONE;
+ pm_runtime_get_noresume(dev);
+
+ if (unlikely(!pm_runtime_active(dev)))
+ goto out_rpm_put;
+
spin_lock(&priv->lock);
/* Network control/Best effort queue RX/TX */
@@ -1272,6 +1298,9 @@ static irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q)
result = IRQ_HANDLED;
spin_unlock(&priv->lock);
+
+out_rpm_put:
+ pm_runtime_put_noidle(dev);
return result;
}
@@ -1746,85 +1775,21 @@ static const struct ethtool_ops ravb_ethtool_ops = {
.set_wol = ravb_set_wol,
};
-static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
- struct net_device *ndev, struct device *dev,
- const char *ch)
-{
- char *name;
- int error;
-
- name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
- if (!name)
- return -ENOMEM;
- error = request_irq(irq, handler, 0, name, ndev);
- if (error)
- netdev_err(ndev, "cannot request IRQ %s\n", name);
-
- return error;
-}
-
/* Network device open function for Ethernet AVB */
static int ravb_open(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info;
- struct platform_device *pdev = priv->pdev;
- struct device *dev = &pdev->dev;
int error;
napi_enable(&priv->napi[RAVB_BE]);
if (info->nc_queues)
napi_enable(&priv->napi[RAVB_NC]);
- if (!info->multi_irqs) {
- error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED,
- ndev->name, ndev);
- if (error) {
- netdev_err(ndev, "cannot request IRQ\n");
- goto out_napi_off;
- }
- } else {
- error = ravb_hook_irq(ndev->irq, ravb_multi_interrupt, ndev,
- dev, "ch22:multi");
- if (error)
- goto out_napi_off;
- error = ravb_hook_irq(priv->emac_irq, ravb_emac_interrupt, ndev,
- dev, "ch24:emac");
- if (error)
- goto out_free_irq;
- error = ravb_hook_irq(priv->rx_irqs[RAVB_BE], ravb_be_interrupt,
- ndev, dev, "ch0:rx_be");
- if (error)
- goto out_free_irq_emac;
- error = ravb_hook_irq(priv->tx_irqs[RAVB_BE], ravb_be_interrupt,
- ndev, dev, "ch18:tx_be");
- if (error)
- goto out_free_irq_be_rx;
- error = ravb_hook_irq(priv->rx_irqs[RAVB_NC], ravb_nc_interrupt,
- ndev, dev, "ch1:rx_nc");
- if (error)
- goto out_free_irq_be_tx;
- error = ravb_hook_irq(priv->tx_irqs[RAVB_NC], ravb_nc_interrupt,
- ndev, dev, "ch19:tx_nc");
- if (error)
- goto out_free_irq_nc_rx;
-
- if (info->err_mgmt_irqs) {
- error = ravb_hook_irq(priv->erra_irq, ravb_multi_interrupt,
- ndev, dev, "err_a");
- if (error)
- goto out_free_irq_nc_tx;
- error = ravb_hook_irq(priv->mgmta_irq, ravb_multi_interrupt,
- ndev, dev, "mgmt_a");
- if (error)
- goto out_free_irq_erra;
- }
- }
-
/* Device init */
error = ravb_dmac_init(ndev);
if (error)
- goto out_free_irq_mgmta;
+ goto out_napi_off;
ravb_emac_init(ndev);
/* Initialise PTP Clock driver */
@@ -1845,26 +1810,6 @@ static int ravb_open(struct net_device *ndev)
if (info->gptp)
ravb_ptp_stop(ndev);
ravb_stop_dma(ndev);
-out_free_irq_mgmta:
- if (!info->multi_irqs)
- goto out_free_irq;
- if (info->err_mgmt_irqs)
- free_irq(priv->mgmta_irq, ndev);
-out_free_irq_erra:
- if (info->err_mgmt_irqs)
- free_irq(priv->erra_irq, ndev);
-out_free_irq_nc_tx:
- free_irq(priv->tx_irqs[RAVB_NC], ndev);
-out_free_irq_nc_rx:
- free_irq(priv->rx_irqs[RAVB_NC], ndev);
-out_free_irq_be_tx:
- free_irq(priv->tx_irqs[RAVB_BE], ndev);
-out_free_irq_be_rx:
- free_irq(priv->rx_irqs[RAVB_BE], ndev);
-out_free_irq_emac:
- free_irq(priv->emac_irq, ndev);
-out_free_irq:
- free_irq(ndev->irq, ndev);
out_napi_off:
if (info->nc_queues)
napi_disable(&priv->napi[RAVB_NC]);
@@ -2219,19 +2164,6 @@ static int ravb_close(struct net_device *ndev)
cancel_work_sync(&priv->work);
- if (info->multi_irqs) {
- free_irq(priv->tx_irqs[RAVB_NC], ndev);
- free_irq(priv->rx_irqs[RAVB_NC], ndev);
- free_irq(priv->tx_irqs[RAVB_BE], ndev);
- free_irq(priv->rx_irqs[RAVB_BE], ndev);
- free_irq(priv->emac_irq, ndev);
- if (info->err_mgmt_irqs) {
- free_irq(priv->erra_irq, ndev);
- free_irq(priv->mgmta_irq, ndev);
- }
- }
- free_irq(ndev->irq, ndev);
-
if (info->nc_queues)
napi_disable(&priv->napi[RAVB_NC]);
napi_disable(&priv->napi[RAVB_BE]);
@@ -2655,6 +2587,90 @@ static void ravb_parse_delay_mode(struct device_node *np, struct net_device *nde
}
}
+static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
+ const char *ch, int *irq, irq_handler_t handler)
+{
+ struct platform_device *pdev = priv->pdev;
+ struct net_device *ndev = priv->ndev;
+ struct device *dev = &pdev->dev;
+ const char *dev_name;
+ unsigned long flags;
+ int error;
+
+ if (irq_name) {
+ dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
+ if (!dev_name)
+ return -ENOMEM;
+
+ *irq = platform_get_irq_byname(pdev, irq_name);
+ flags = 0;
+ } else {
+ dev_name = ndev->name;
+ *irq = platform_get_irq(pdev, 0);
+ flags = IRQF_SHARED;
+ }
+ if (*irq < 0)
+ return *irq;
+
+ error = devm_request_irq(dev, *irq, handler, flags, dev_name, ndev);
+ if (error)
+ netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
+
+ return error;
+}
+
+static int ravb_setup_irqs(struct ravb_private *priv)
+{
+ const struct ravb_hw_info *info = priv->info;
+ struct net_device *ndev = priv->ndev;
+ const char *irq_name, *emac_irq_name;
+ int error, irq;
+
+ if (!info->multi_irqs)
+ return ravb_setup_irq(priv, NULL, NULL, &ndev->irq, ravb_interrupt);
+
+ if (info->err_mgmt_irqs) {
+ irq_name = "dia";
+ emac_irq_name = "line3";
+ } else {
+ irq_name = "ch22";
+ emac_irq_name = "ch24";
+ }
+
+ error = ravb_setup_irq(priv, irq_name, "ch22:multi", &ndev->irq, ravb_multi_interrupt);
+ if (error)
+ return error;
+
+ error = ravb_setup_irq(priv, emac_irq_name, "ch24:emac", &priv->emac_irq,
+ ravb_emac_interrupt);
+ if (error)
+ return error;
+
+ if (info->err_mgmt_irqs) {
+ error = ravb_setup_irq(priv, "err_a", "err_a", &irq, ravb_multi_interrupt);
+ if (error)
+ return error;
+
+ error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &irq, ravb_multi_interrupt);
+ if (error)
+ return error;
+ }
+
+ error = ravb_setup_irq(priv, "ch0", "ch0:rx_be", &irq, ravb_be_interrupt);
+ if (error)
+ return error;
+
+ error = ravb_setup_irq(priv, "ch1", "ch1:rx_nc", &irq, ravb_nc_interrupt);
+ if (error)
+ return error;
+
+ error = ravb_setup_irq(priv, "ch18", "ch18:tx_be", &irq, ravb_be_interrupt);
+ if (error)
+ return error;
+
+ return ravb_setup_irq(priv, "ch19", "ch19:tx_nc", &irq, ravb_nc_interrupt);
+}
+
static void ravb_set_delay_mode(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
@@ -2674,9 +2690,8 @@ static int ravb_probe(struct platform_device *pdev)
struct reset_control *rstc;
struct ravb_private *priv;
struct net_device *ndev;
- int error, irq, q;
struct resource *res;
- int i;
+ int error, q;
if (!np) {
dev_err(&pdev->dev,
@@ -2703,20 +2718,6 @@ static int ravb_probe(struct platform_device *pdev)
if (error)
goto out_free_netdev;
- if (info->multi_irqs) {
- if (info->err_mgmt_irqs)
- irq = platform_get_irq_byname(pdev, "dia");
- else
- irq = platform_get_irq_byname(pdev, "ch22");
- } else {
- irq = platform_get_irq(pdev, 0);
- }
- if (irq < 0) {
- error = irq;
- goto out_reset_assert;
- }
- ndev->irq = irq;
-
SET_NETDEV_DEV(ndev, &pdev->dev);
priv = netdev_priv(ndev);
@@ -2731,6 +2732,10 @@ static int ravb_probe(struct platform_device *pdev)
priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE;
}
+ error = ravb_setup_irqs(priv);
+ if (error)
+ goto out_reset_assert;
+
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
error = PTR_ERR(priv->clk);
@@ -2778,50 +2783,6 @@ static int ravb_probe(struct platform_device *pdev)
priv->avb_link_active_low =
of_property_read_bool(np, "renesas,ether-link-active-low");
- if (info->multi_irqs) {
- if (info->err_mgmt_irqs)
- irq = platform_get_irq_byname(pdev, "line3");
- else
- irq = platform_get_irq_byname(pdev, "ch24");
- if (irq < 0) {
- error = irq;
- goto out_rpm_put;
- }
- priv->emac_irq = irq;
- for (i = 0; i < NUM_RX_QUEUE; i++) {
- irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]);
- if (irq < 0) {
- error = irq;
- goto out_rpm_put;
- }
- priv->rx_irqs[i] = irq;
- }
- for (i = 0; i < NUM_TX_QUEUE; i++) {
- irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]);
- if (irq < 0) {
- error = irq;
- goto out_rpm_put;
- }
- priv->tx_irqs[i] = irq;
- }
-
- if (info->err_mgmt_irqs) {
- irq = platform_get_irq_byname(pdev, "err_a");
- if (irq < 0) {
- error = irq;
- goto out_rpm_put;
- }
- priv->erra_irq = irq;
-
- irq = platform_get_irq_byname(pdev, "mgmt_a");
- if (irq < 0) {
- error = irq;
- goto out_rpm_put;
- }
- priv->mgmta_irq = irq;
- }
- }
-
ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
ndev->min_mtu = ETH_MIN_MTU;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6.1.y 5/7] net: ravb: Get rid of the temporary variable irq
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
` (2 preceding siblings ...)
2026-09-09 17:17 ` [PATCH 6.1.y 4/7] net: ravb: Move getting/requesting IRQs in the probe() method Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 6/7] net: ravb: avoid dereferencing an invalid PTP clock Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 7/7] net: ravb: serialize PTP clock teardown Sasha Levin
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable; +Cc: Claudiu Beznea, Sergey Shtylyov, David S. Miller, Sasha Levin
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
[ Upstream commit a260f080660ef8bac97404dd0b9ddbe35a608426 ]
The 4th argument of ravb_setup_irq() is used to save the IRQ number that
will be further used by the driver code. Not all ravb_setup_irqs() calls
need to save the IRQ number. The previous code used to pass a dummy
variable as the 4th argument in case the IRQ is not needed for further
usage. That is not necessary as the code from ravb_setup_irq() can detect
by itself if the IRQ needs to be saved. Thus, get rid of the code that is
not needed.
Reported-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 1cb9663789c5 ("net: ravb: serialize PTP clock teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb_main.c | 29 +++++++++++++-----------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 0da019d1a2fd5..e13bf0a0f312a 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2595,24 +2595,27 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
struct device *dev = &pdev->dev;
const char *dev_name;
unsigned long flags;
- int error;
+ int error, irq_num;
if (irq_name) {
dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
if (!dev_name)
return -ENOMEM;
- *irq = platform_get_irq_byname(pdev, irq_name);
+ irq_num = platform_get_irq_byname(pdev, irq_name);
flags = 0;
} else {
dev_name = ndev->name;
- *irq = platform_get_irq(pdev, 0);
+ irq_num = platform_get_irq(pdev, 0);
flags = IRQF_SHARED;
}
- if (*irq < 0)
- return *irq;
+ if (irq_num < 0)
+ return irq_num;
+
+ if (irq)
+ *irq = irq_num;
- error = devm_request_irq(dev, *irq, handler, flags, dev_name, ndev);
+ error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev);
if (error)
netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
@@ -2624,7 +2627,7 @@ static int ravb_setup_irqs(struct ravb_private *priv)
const struct ravb_hw_info *info = priv->info;
struct net_device *ndev = priv->ndev;
const char *irq_name, *emac_irq_name;
- int error, irq;
+ int error;
if (!info->multi_irqs)
return ravb_setup_irq(priv, NULL, NULL, &ndev->irq, ravb_interrupt);
@@ -2647,28 +2650,28 @@ static int ravb_setup_irqs(struct ravb_private *priv)
return error;
if (info->err_mgmt_irqs) {
- error = ravb_setup_irq(priv, "err_a", "err_a", &irq, ravb_multi_interrupt);
+ error = ravb_setup_irq(priv, "err_a", "err_a", NULL, ravb_multi_interrupt);
if (error)
return error;
- error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &irq, ravb_multi_interrupt);
+ error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", NULL, ravb_multi_interrupt);
if (error)
return error;
}
- error = ravb_setup_irq(priv, "ch0", "ch0:rx_be", &irq, ravb_be_interrupt);
+ error = ravb_setup_irq(priv, "ch0", "ch0:rx_be", NULL, ravb_be_interrupt);
if (error)
return error;
- error = ravb_setup_irq(priv, "ch1", "ch1:rx_nc", &irq, ravb_nc_interrupt);
+ error = ravb_setup_irq(priv, "ch1", "ch1:rx_nc", NULL, ravb_nc_interrupt);
if (error)
return error;
- error = ravb_setup_irq(priv, "ch18", "ch18:tx_be", &irq, ravb_be_interrupt);
+ error = ravb_setup_irq(priv, "ch18", "ch18:tx_be", NULL, ravb_be_interrupt);
if (error)
return error;
- return ravb_setup_irq(priv, "ch19", "ch19:tx_nc", &irq, ravb_nc_interrupt);
+ return ravb_setup_irq(priv, "ch19", "ch19:tx_nc", NULL, ravb_nc_interrupt);
}
static void ravb_set_delay_mode(struct net_device *ndev)
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6.1.y 6/7] net: ravb: avoid dereferencing an invalid PTP clock
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
` (3 preceding siblings ...)
2026-09-09 17:17 ` [PATCH 6.1.y 5/7] net: ravb: Get rid of the temporary variable irq Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
2026-09-09 17:17 ` [PATCH 6.1.y 7/7] net: ravb: serialize PTP clock teardown Sasha Levin
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable; +Cc: Xuanqiang Luo, Vadim Fedorenko, Jakub Kicinski, Sasha Levin
From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
[ Upstream commit 1f77af0aaf277413ff32f6ff8c2c4282bd64c897 ]
The PTP clock is unavailable before the first open, so querying its
index can dereference a NULL pointer. Registration failures can also
leave an error pointer in priv->ptp.clock.
Cache the PHC index separately and report -1 while no clock is
registered. Normalize registration errors to NULL and preserve the
static timestamping capabilities.
Fixes: a0d2f20650e8 ("Renesas Ethernet AVB PTP clock driver")
Cc: stable@vger.kernel.org
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Link: https://patch.msgid.link/20260811103733.62599-2-xuanqiang.luo@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 1cb9663789c5 ("net: ravb: serialize PTP clock teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb.h | 1 +
drivers/net/ethernet/renesas/ravb_main.c | 3 ++-
drivers/net/ethernet/renesas/ravb_ptp.c | 15 +++++++++++++--
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index e3506888cca6e..8bd94180113d2 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1005,6 +1005,7 @@ struct ravb_ptp_perout {
struct ravb_ptp {
struct ptp_clock *clock;
struct ptp_clock_info info;
+ int phc_index;
u32 default_addend;
u32 current_addend;
int extts[N_EXT_TS];
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index e13bf0a0f312a..faba6bf94a757 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1729,7 +1729,7 @@ static int ravb_get_ts_info(struct net_device *ndev,
(1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
(1 << HWTSTAMP_FILTER_ALL);
- info->phc_index = ptp_clock_index(priv->ptp.clock);
+ info->phc_index = READ_ONCE(priv->ptp.phc_index);
}
return 0;
@@ -2728,6 +2728,7 @@ static int ravb_probe(struct platform_device *pdev)
priv->rstc = rstc;
priv->ndev = ndev;
priv->pdev = pdev;
+ priv->ptp.phc_index = -1;
priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
if (info->nc_queues) {
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index 87c4306d66ecc..97267a0c45a6b 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -332,6 +332,7 @@ void ravb_ptp_interrupt(struct net_device *ndev)
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
{
struct ravb_private *priv = netdev_priv(ndev);
+ struct ptp_clock *clock;
unsigned long flags;
priv->ptp.info = ravb_ptp_info;
@@ -344,7 +345,15 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
ravb_modify(ndev, GCCR, GCCR_TCSS, GCCR_TCSS_ADJGPTP);
spin_unlock_irqrestore(&priv->lock, flags);
- priv->ptp.clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
+ clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
+ if (IS_ERR(clock)) {
+ netdev_err(ndev, "failed to register PTP clock: %pe\n", clock);
+ clock = NULL;
+ }
+
+ priv->ptp.clock = clock;
+ if (clock)
+ WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
}
void ravb_ptp_stop(struct net_device *ndev)
@@ -354,5 +363,7 @@ void ravb_ptp_stop(struct net_device *ndev)
ravb_write(ndev, 0, GIC);
ravb_write(ndev, 0, GIS);
- ptp_clock_unregister(priv->ptp.clock);
+ WRITE_ONCE(priv->ptp.phc_index, -1);
+ if (priv->ptp.clock)
+ ptp_clock_unregister(priv->ptp.clock);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6.1.y 7/7] net: ravb: serialize PTP clock teardown
2026-09-09 17:17 ` [PATCH 6.1.y 1/7] net: ravb: Rely on PM domain to enable gptp_clk Sasha Levin
` (4 preceding siblings ...)
2026-09-09 17:17 ` [PATCH 6.1.y 6/7] net: ravb: avoid dereferencing an invalid PTP clock Sasha Levin
@ 2026-09-09 17:17 ` Sasha Levin
5 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2026-09-09 17:17 UTC (permalink / raw)
To: stable; +Cc: Xuanqiang Luo, Jakub Kicinski, Sasha Levin
From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
[ Upstream commit 1cb9663789c5b7a12fcd419fcca6d6254c398252 ]
ravb_ptp_interrupt() can race with ravb_ptp_stop() and pass the clock to
ptp_clock_event() while ptp_clock_unregister() is freeing it. This can
lead to a use-after-free.
Use READ_ONCE() and WRITE_ONCE() for lockless access to the clock pointer.
Atomically detach it with xchg() before disabling PTP interrupts, then
synchronize all IRQs which can invoke ravb_ptp_interrupt() before
unregistering the detached clock.
A handler which read the old pointer completes before the clock is
unregistered, while later handlers read NULL and skip the event.
Fixes: a0d2f20650e8 ("Renesas Ethernet AVB PTP clock driver")
Cc: stable@vger.kernel.org
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Link: https://patch.msgid.link/20260811103733.62599-3-xuanqiang.luo@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/renesas/ravb.h | 2 ++
drivers/net/ethernet/renesas/ravb_main.c | 6 ++--
drivers/net/ethernet/renesas/ravb_ptp.c | 37 +++++++++++++++++++-----
3 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 8bd94180113d2..866c769929d46 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1090,6 +1090,8 @@ struct ravb_private {
int msg_enable;
int speed;
int emac_irq;
+ int err_irq;
+ int mgmt_irq;
unsigned no_avb_link:1;
unsigned avb_link_active_low:1;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index faba6bf94a757..e8eba5d61d9ad 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2650,11 +2650,13 @@ static int ravb_setup_irqs(struct ravb_private *priv)
return error;
if (info->err_mgmt_irqs) {
- error = ravb_setup_irq(priv, "err_a", "err_a", NULL, ravb_multi_interrupt);
+ error = ravb_setup_irq(priv, "err_a", "err_a", &priv->err_irq,
+ ravb_multi_interrupt);
if (error)
return error;
- error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", NULL, ravb_multi_interrupt);
+ error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &priv->mgmt_irq,
+ ravb_multi_interrupt);
if (error)
return error;
}
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index 97267a0c45a6b..948bfc2ec6a98 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -306,16 +306,17 @@ static const struct ptp_clock_info ravb_ptp_info = {
void ravb_ptp_interrupt(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
+ struct ptp_clock *clock = READ_ONCE(priv->ptp.clock);
u32 gis = ravb_read(ndev, GIS);
gis &= ravb_read(ndev, GIC);
- if (gis & GIS_PTCF) {
+ if ((gis & GIS_PTCF) && clock) {
struct ptp_clock_event event;
event.type = PTP_CLOCK_EXTTS;
event.index = 0;
event.timestamp = ravb_read(ndev, GCPT);
- ptp_clock_event(priv->ptp.clock, &event);
+ ptp_clock_event(clock, &event);
}
if (gis & GIS_PTMF) {
struct ravb_ptp_perout *perout = priv->ptp.perout;
@@ -351,19 +352,39 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
clock = NULL;
}
- priv->ptp.clock = clock;
+ WRITE_ONCE(priv->ptp.clock, clock);
if (clock)
WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
}
-void ravb_ptp_stop(struct net_device *ndev)
+static void ravb_ptp_disable(struct net_device *ndev)
{
- struct ravb_private *priv = netdev_priv(ndev);
-
ravb_write(ndev, 0, GIC);
ravb_write(ndev, 0, GIS);
+}
+
+static void ravb_ptp_sync_irqs(struct net_device *ndev)
+{
+ struct ravb_private *priv = netdev_priv(ndev);
+
+ synchronize_irq(ndev->irq);
+ if (priv->info->err_mgmt_irqs) {
+ synchronize_irq(priv->err_irq);
+ synchronize_irq(priv->mgmt_irq);
+ }
+}
+
+void ravb_ptp_stop(struct net_device *ndev)
+{
+ struct ravb_private *priv = netdev_priv(ndev);
+ struct ptp_clock *clock;
WRITE_ONCE(priv->ptp.phc_index, -1);
- if (priv->ptp.clock)
- ptp_clock_unregister(priv->ptp.clock);
+ clock = xchg(&priv->ptp.clock, NULL);
+
+ ravb_ptp_disable(ndev);
+ ravb_ptp_sync_irqs(ndev);
+
+ if (clock)
+ ptp_clock_unregister(clock);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread