Commit fc136368 authored by David S. Miller's avatar David S. Miller

Merge branch 'ravb-rutime-PM-support'

Claudiu Beznea says:

====================
net: ravb: Add runtime PM support (part 2)

Series adds runtime PM support for the ravb driver. This is a continuation
of [1].

There are 5 more preparation patches (patches 1-5) and patch 6
adds runtime PM support.

Patches in this series were part of [2].

Changes in v4:
- remove unnecessary code from patch 4/6
- improve the code in patch 5/6

Changes in v3:
- fixed typos
- added patch "net: ravb: Move the update of ndev->features to
  ravb_set_features()"
- changes title of patch "net: ravb: Do not apply RX checksum
  settings to hardware if the interface is down" from v2 into
  "net: ravb: Do not apply features to hardware if the interface
  is down", changed patch description and updated the patch
- collected tags

Changes in v2:
- address review comments
- in patch 4/5 take into account the latest changes introduced
  in ravb_set_features_gbeth()

Changes since [2]:
- patch 1/5 is new
- use pm_runtime_get_noresume() and pm_runtime_active() in patches
  3/5, 4/5
- fixed higlighted typos in patch 4/5

[1] https://lore.kernel.org/all/20240202084136.3426492-1-claudiu.beznea.uj@bp.renesas.com/
[2] https://lore.kernel.org/all/20240105082339.1468817-1-claudiu.beznea.uj@bp.renesas.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 31f26e4f 48f894ab
...@@ -1935,16 +1935,21 @@ static int ravb_open(struct net_device *ndev) ...@@ -1935,16 +1935,21 @@ static int ravb_open(struct net_device *ndev)
{ {
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct device *dev = &priv->pdev->dev;
int error; int error;
napi_enable(&priv->napi[RAVB_BE]); napi_enable(&priv->napi[RAVB_BE]);
if (info->nc_queues) if (info->nc_queues)
napi_enable(&priv->napi[RAVB_NC]); napi_enable(&priv->napi[RAVB_NC]);
error = pm_runtime_resume_and_get(dev);
if (error < 0)
goto out_napi_off;
/* Set AVB config mode */ /* Set AVB config mode */
error = ravb_set_config_mode(ndev); error = ravb_set_config_mode(ndev);
if (error) if (error)
goto out_napi_off; goto out_rpm_put;
ravb_set_delay_mode(ndev); ravb_set_delay_mode(ndev);
ravb_write(ndev, priv->desc_bat_dma, DBAT); ravb_write(ndev, priv->desc_bat_dma, DBAT);
...@@ -1978,6 +1983,9 @@ static int ravb_open(struct net_device *ndev) ...@@ -1978,6 +1983,9 @@ static int ravb_open(struct net_device *ndev)
ravb_stop_dma(ndev); ravb_stop_dma(ndev);
out_set_reset: out_set_reset:
ravb_set_opmode(ndev, CCC_OPC_RESET); ravb_set_opmode(ndev, CCC_OPC_RESET);
out_rpm_put:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
out_napi_off: out_napi_off:
if (info->nc_queues) if (info->nc_queues)
napi_disable(&priv->napi[RAVB_NC]); napi_disable(&priv->napi[RAVB_NC]);
...@@ -2244,8 +2252,15 @@ static struct net_device_stats *ravb_get_stats(struct net_device *ndev) ...@@ -2244,8 +2252,15 @@ static struct net_device_stats *ravb_get_stats(struct net_device *ndev)
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct net_device_stats *nstats, *stats0, *stats1; struct net_device_stats *nstats, *stats0, *stats1;
struct device *dev = &priv->pdev->dev;
nstats = &ndev->stats; nstats = &ndev->stats;
pm_runtime_get_noresume(dev);
if (!pm_runtime_active(dev))
goto out_rpm_put;
stats0 = &priv->stats[RAVB_BE]; stats0 = &priv->stats[RAVB_BE];
if (info->tx_counters) { if (info->tx_counters) {
...@@ -2287,6 +2302,8 @@ static struct net_device_stats *ravb_get_stats(struct net_device *ndev) ...@@ -2287,6 +2302,8 @@ static struct net_device_stats *ravb_get_stats(struct net_device *ndev)
nstats->rx_over_errors += stats1->rx_over_errors; nstats->rx_over_errors += stats1->rx_over_errors;
} }
out_rpm_put:
pm_runtime_put_noidle(dev);
return nstats; return nstats;
} }
...@@ -2309,6 +2326,8 @@ static int ravb_close(struct net_device *ndev) ...@@ -2309,6 +2326,8 @@ static int ravb_close(struct net_device *ndev)
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct ravb_tstamp_skb *ts_skb, *ts_skb2; struct ravb_tstamp_skb *ts_skb, *ts_skb2;
struct device *dev = &priv->pdev->dev;
int error;
netif_tx_stop_all_queues(ndev); netif_tx_stop_all_queues(ndev);
...@@ -2317,6 +2336,14 @@ static int ravb_close(struct net_device *ndev) ...@@ -2317,6 +2336,14 @@ static int ravb_close(struct net_device *ndev)
ravb_write(ndev, 0, RIC2); ravb_write(ndev, 0, RIC2);
ravb_write(ndev, 0, TIC); ravb_write(ndev, 0, TIC);
/* PHY disconnect */
if (ndev->phydev) {
phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
}
/* Stop PTP Clock driver */ /* Stop PTP Clock driver */
if (info->gptp || info->ccc_gac) if (info->gptp || info->ccc_gac)
ravb_ptp_stop(ndev); ravb_ptp_stop(ndev);
...@@ -2335,14 +2362,6 @@ static int ravb_close(struct net_device *ndev) ...@@ -2335,14 +2362,6 @@ static int ravb_close(struct net_device *ndev)
} }
} }
/* PHY disconnect */
if (ndev->phydev) {
phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
}
cancel_work_sync(&priv->work); cancel_work_sync(&priv->work);
if (info->nc_queues) if (info->nc_queues)
...@@ -2354,8 +2373,18 @@ static int ravb_close(struct net_device *ndev) ...@@ -2354,8 +2373,18 @@ static int ravb_close(struct net_device *ndev)
if (info->nc_queues) if (info->nc_queues)
ravb_ring_free(ndev, RAVB_NC); ravb_ring_free(ndev, RAVB_NC);
/* Update statistics. */
ravb_get_stats(ndev);
/* Set reset mode. */ /* Set reset mode. */
return ravb_set_opmode(ndev, CCC_OPC_RESET); error = ravb_set_opmode(ndev, CCC_OPC_RESET);
if (error)
return error;
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
} }
static int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req) static int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req)
...@@ -2526,7 +2555,6 @@ static int ravb_set_features_gbeth(struct net_device *ndev, ...@@ -2526,7 +2555,6 @@ static int ravb_set_features_gbeth(struct net_device *ndev,
goto done; goto done;
} }
ndev->features = features;
done: done:
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
...@@ -2541,8 +2569,6 @@ static int ravb_set_features_rcar(struct net_device *ndev, ...@@ -2541,8 +2569,6 @@ static int ravb_set_features_rcar(struct net_device *ndev,
if (changed & NETIF_F_RXCSUM) if (changed & NETIF_F_RXCSUM)
ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM); ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
ndev->features = features;
return 0; return 0;
} }
...@@ -2551,8 +2577,24 @@ static int ravb_set_features(struct net_device *ndev, ...@@ -2551,8 +2577,24 @@ static int ravb_set_features(struct net_device *ndev,
{ {
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct device *dev = &priv->pdev->dev;
int ret;
pm_runtime_get_noresume(dev);
if (pm_runtime_active(dev))
ret = info->set_feature(ndev, features);
else
ret = 0;
pm_runtime_put_noidle(dev);
if (ret)
return ret;
ndev->features = features;
return info->set_feature(ndev, features); return 0;
} }
static const struct net_device_ops ravb_netdev_ops = { static const struct net_device_ops ravb_netdev_ops = {
...@@ -2743,24 +2785,27 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name, ...@@ -2743,24 +2785,27 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const char *dev_name; const char *dev_name;
unsigned long flags; unsigned long flags;
int error; int error, irq_num;
if (irq_name) { if (irq_name) {
dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
if (!dev_name) if (!dev_name)
return -ENOMEM; return -ENOMEM;
*irq = platform_get_irq_byname(pdev, irq_name); irq_num = platform_get_irq_byname(pdev, irq_name);
flags = 0; flags = 0;
} else { } else {
dev_name = ndev->name; dev_name = ndev->name;
*irq = platform_get_irq(pdev, 0); irq_num = platform_get_irq(pdev, 0);
flags = IRQF_SHARED; flags = IRQF_SHARED;
} }
if (*irq < 0) if (irq_num < 0)
return *irq; return irq_num;
error = devm_request_irq(dev, *irq, handler, flags, dev_name, ndev); if (irq)
*irq = irq_num;
error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev);
if (error) if (error)
netdev_err(ndev, "cannot request IRQ %s\n", dev_name); netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
...@@ -2772,7 +2817,7 @@ static int ravb_setup_irqs(struct ravb_private *priv) ...@@ -2772,7 +2817,7 @@ static int ravb_setup_irqs(struct ravb_private *priv)
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct net_device *ndev = priv->ndev; struct net_device *ndev = priv->ndev;
const char *irq_name, *emac_irq_name; const char *irq_name, *emac_irq_name;
int error, irq; int error;
if (!info->multi_irqs) if (!info->multi_irqs)
return ravb_setup_irq(priv, NULL, NULL, &ndev->irq, ravb_interrupt); return ravb_setup_irq(priv, NULL, NULL, &ndev->irq, ravb_interrupt);
...@@ -2795,28 +2840,28 @@ static int ravb_setup_irqs(struct ravb_private *priv) ...@@ -2795,28 +2840,28 @@ static int ravb_setup_irqs(struct ravb_private *priv)
return error; return error;
if (info->err_mgmt_irqs) { 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) if (error)
return 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) if (error)
return 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) if (error)
return 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) if (error)
return 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) if (error)
return 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 int ravb_probe(struct platform_device *pdev) static int ravb_probe(struct platform_device *pdev)
...@@ -2894,6 +2939,8 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2894,6 +2939,8 @@ static int ravb_probe(struct platform_device *pdev)
clk_prepare(priv->refclk); clk_prepare(priv->refclk);
platform_set_drvdata(pdev, ndev); platform_set_drvdata(pdev, ndev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
error = pm_runtime_resume_and_get(&pdev->dev); error = pm_runtime_resume_and_get(&pdev->dev);
if (error < 0) if (error < 0)
...@@ -2999,6 +3046,9 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2999,6 +3046,9 @@ static int ravb_probe(struct platform_device *pdev)
netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n", netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n",
(u32)ndev->base_addr, ndev->dev_addr, ndev->irq); (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
return 0; return 0;
out_napi_del: out_napi_del:
...@@ -3016,6 +3066,7 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -3016,6 +3066,7 @@ static int ravb_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
out_rpm_disable: out_rpm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_unprepare(priv->refclk); clk_unprepare(priv->refclk);
out_reset_assert: out_reset_assert:
reset_control_assert(rstc); reset_control_assert(rstc);
...@@ -3029,6 +3080,12 @@ static void ravb_remove(struct platform_device *pdev) ...@@ -3029,6 +3080,12 @@ static void ravb_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info; const struct ravb_hw_info *info = priv->info;
struct device *dev = &priv->pdev->dev;
int error;
error = pm_runtime_resume_and_get(dev);
if (error < 0)
return;
unregister_netdev(ndev); unregister_netdev(ndev);
if (info->nc_queues) if (info->nc_queues)
...@@ -3040,8 +3097,9 @@ static void ravb_remove(struct platform_device *pdev) ...@@ -3040,8 +3097,9 @@ static void ravb_remove(struct platform_device *pdev)
dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
priv->desc_bat_dma); priv->desc_bat_dma);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync_suspend(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(dev);
clk_unprepare(priv->refclk); clk_unprepare(priv->refclk);
reset_control_assert(priv->rstc); reset_control_assert(priv->rstc);
free_netdev(ndev); free_netdev(ndev);
...@@ -3123,6 +3181,10 @@ static int ravb_suspend(struct device *dev) ...@@ -3123,6 +3181,10 @@ static int ravb_suspend(struct device *dev)
if (ret) if (ret)
return ret; return ret;
ret = pm_runtime_force_suspend(&priv->pdev->dev);
if (ret)
return ret;
reset_assert: reset_assert:
return reset_control_assert(priv->rstc); return reset_control_assert(priv->rstc);
} }
...@@ -3145,16 +3207,28 @@ static int ravb_resume(struct device *dev) ...@@ -3145,16 +3207,28 @@ static int ravb_resume(struct device *dev)
ret = ravb_wol_restore(ndev); ret = ravb_wol_restore(ndev);
if (ret) if (ret)
return ret; return ret;
} else {
ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
} }
/* Reopening the interface will restore the device to the working state. */ /* Reopening the interface will restore the device to the working state. */
ret = ravb_open(ndev); ret = ravb_open(ndev);
if (ret < 0) if (ret < 0)
return ret; goto out_rpm_put;
ravb_set_rx_mode(ndev); ravb_set_rx_mode(ndev);
netif_device_attach(ndev); netif_device_attach(ndev);
return 0;
out_rpm_put:
if (!priv->wol_enabled) {
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment