mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
watchdog fixes for v7.3-rc4
* da9062, da9063: Fix suspend/resume handling of HW_RUNNING watchdog * digicolor, rtd119x, and rzv2h: Avoid division by zero if clock rate is 0 * msc313e: Fix premature reset during timeout update, and propagate error code in resume() * sp5100_tco: Fix pci_dev reference leak in sp5100_tco_init() * starfive-wdt: Fix runtime PM leak in starfive_wdt_pm_start() -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmqtZJEACgkQyx8mb86f mYGnwA/8C90wOrDbHonYx0SahuJaYniOmz6yHCuAR1AwtzKfXDua3WJ7ry4WfZXN WCACTcFCUp1CiLvstwpX7nDKGReYG47FOq6Rbou+JaJo43m9SGga5IGxKM28MBy7 F4TH3CDMSOcomlgPYeXc5jx0oRkNXyDPMDHtbCOM5h+WwJb0Zxtfh+77l5q2LrQg D7nIGCkoztl7PDIgbvYESp9DYVdUgT6paeIRjJbs5BCwmNleU9LInDPDAtcXHnRp cyCa8FlfPrQMxhtbF1YQyaEdU04GlAwtHW4HE55tcxY3pTE/9qqA5SUzQBDXT2gO yCCG1qIFOmJY6QnlSfIYpHZtNxcpA75d8fQvqm14H+ACxkbaRF1d+sobtJTTckTD WBSr6RlrB5f/DAltqbV2OAsLddhBl4rQkW2RiljTW4C4pUiedPoSR8StTpnM6lC3 VBpUdYp7tCIWihX/v/v+iRK1Y7JWVM+lhQnMpqBtpLtl3k7VLCLoFsmSbz0hHhu6 kAJ1ZWeBy2xYgiGOM+D361iKhefjsZk9tdrC8IxriJ/gUwlcazELqqcsvU+I5ebN sutAYvE6Vdl5qwiLIRRHNpHvKm0wu9URIpPJrdwDtAIbaT3joSZIkV3TA7ZFBwGG tU4Z9ok0O4N4DDPv0CAg82lXBrMiWt3agYKKkhKTsmKROqqWVa8= =oqFf -----END PGP SIGNATURE----- Merge tag 'watchdog-fixes-for-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull watchdog fixes from Guenter Roeck: - Fix suspend/resume handling of HW_RUNNING watchdog (da9062, da9063) - Avoid division by zero if clock rate is 0 (digicolor, rtd119x, and rzv2h) - Fix premature reset during timeout update, and propagate error code in msc313e resume() - Fix pci_dev reference leak in sp5100_tco_init() - Fix runtime PM leak in starfive_wdt_pm_start() * tag 'watchdog-fixes-for-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: watchdog: da9063: fix suspend/resume handling of HW_RUNNING watchdog watchdog: starfive-wdt: Fix runtime PM leak in starfive_wdt_pm_start() watchdog: da9062: fix suspend/resume handling of HW_RUNNING watchdog watchdog: msc313e: Fix premature reset during timeout update watchdog: msc313e: Propagate error code in resume() watchdog: rzv2h: Avoid division by zero watchdog: rtd119x: Avoid division by zero watchdog: digicolor: Avoid division by zero watchdog: sp5100_tco: Fix pci_dev reference leak in sp5100_tco_init()
This commit is contained in:
commit
928ba50514
|
|
@ -256,7 +256,7 @@ static int __maybe_unused da9062_wdt_suspend(struct device *dev)
|
|||
if (!wdt->use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
if (watchdog_active(wdd) || watchdog_hw_running(wdd))
|
||||
return da9062_wdt_stop(wdd);
|
||||
|
||||
return 0;
|
||||
|
|
@ -270,7 +270,7 @@ static int __maybe_unused da9062_wdt_resume(struct device *dev)
|
|||
if (!wdt->use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
if (watchdog_active(wdd) || watchdog_hw_running(wdd))
|
||||
return da9062_wdt_start(wdd);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ static int da9063_wdt_suspend(struct device *dev)
|
|||
if (!da9063->use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
if (watchdog_active(wdd) || watchdog_hw_running(wdd))
|
||||
return da9063_wdt_stop(wdd);
|
||||
|
||||
return 0;
|
||||
|
|
@ -285,7 +285,7 @@ static int da9063_wdt_resume(struct device *dev)
|
|||
if (!da9063->use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
if (watchdog_active(wdd) || watchdog_hw_running(wdd))
|
||||
return da9063_wdt_start(wdd);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct dc_wdt {
|
|||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
spinlock_t lock;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
static unsigned timeout;
|
||||
|
|
@ -61,7 +62,7 @@ static int dc_wdt_start(struct watchdog_device *wdog)
|
|||
{
|
||||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
|
||||
dc_wdt_set(wdt, wdog->timeout * clk_get_rate(wdt->clk));
|
||||
dc_wdt_set(wdt, wdog->timeout * wdt->rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ static int dc_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t)
|
|||
{
|
||||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
|
||||
dc_wdt_set(wdt, t * clk_get_rate(wdt->clk));
|
||||
dc_wdt_set(wdt, t * wdt->rate);
|
||||
wdog->timeout = t;
|
||||
|
||||
return 0;
|
||||
|
|
@ -90,7 +91,7 @@ static unsigned int dc_wdt_get_timeleft(struct watchdog_device *wdog)
|
|||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
uint32_t count = readl_relaxed(wdt->base + TIMER_A_COUNT);
|
||||
|
||||
return count / clk_get_rate(wdt->clk);
|
||||
return count / wdt->rate;
|
||||
}
|
||||
|
||||
static const struct watchdog_ops dc_wdt_ops = {
|
||||
|
|
@ -130,7 +131,11 @@ static int dc_wdt_probe(struct platform_device *pdev)
|
|||
wdt->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(wdt->clk))
|
||||
return PTR_ERR(wdt->clk);
|
||||
dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk);
|
||||
|
||||
wdt->rate = clk_get_rate(wdt->clk);
|
||||
if (!wdt->rate)
|
||||
return -EINVAL;
|
||||
dc_wdt_wdd.max_timeout = U32_MAX / wdt->rate;
|
||||
dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout;
|
||||
dc_wdt_wdd.parent = dev;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ static void msc313e_wdt_set_hw_timeout(struct msc313e_wdt_priv *priv,
|
|||
{
|
||||
u32 t = timeout * clk_get_rate(priv->clk);
|
||||
|
||||
/* Clear before to prevent premature reset during non-atomic updates. */
|
||||
writew(1, priv->base + REG_WDT_CLR);
|
||||
|
||||
writew(t & 0xffff, priv->base + REG_WDT_MAX_PRD_L);
|
||||
writew((t >> 16) & 0xffff, priv->base + REG_WDT_MAX_PRD_H);
|
||||
writew(1, priv->base + REG_WDT_CLR);
|
||||
|
|
@ -76,6 +79,9 @@ static int msc313e_wdt_stop(struct watchdog_device *wdev)
|
|||
{
|
||||
struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
/* Clear before to prevent premature reset during non-atomic updates. */
|
||||
writew(1, priv->base + REG_WDT_CLR);
|
||||
|
||||
writew(0, priv->base + REG_WDT_MAX_PRD_L);
|
||||
writew(0, priv->base + REG_WDT_MAX_PRD_H);
|
||||
writew(0, priv->base + REG_WDT_CLR);
|
||||
|
|
@ -191,11 +197,15 @@ static int __maybe_unused msc313e_wdt_suspend(struct device *dev)
|
|||
static int __maybe_unused msc313e_wdt_resume(struct device *dev)
|
||||
{
|
||||
struct msc313e_wdt_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (watchdog_active(&priv->wdev) || watchdog_hw_running(&priv->wdev))
|
||||
msc313e_wdt_start(&priv->wdev);
|
||||
if (watchdog_active(&priv->wdev) || watchdog_hw_running(&priv->wdev)) {
|
||||
ret = msc313e_wdt_start(&priv->wdev);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to restart watchdog (err=%d)\n", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(msc313e_wdt_pm_ops, msc313e_wdt_suspend, msc313e_wdt_resume);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ static int rtd119x_wdt_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rtd119x_watchdog_device *data;
|
||||
unsigned long rate;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
|
@ -111,10 +112,14 @@ static int rtd119x_wdt_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(data->clk))
|
||||
return PTR_ERR(data->clk);
|
||||
|
||||
rate = clk_get_rate(data->clk);
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
data->wdt_dev.info = &rtd119x_wdt_info;
|
||||
data->wdt_dev.ops = &rtd119x_wdt_ops;
|
||||
data->wdt_dev.timeout = 120;
|
||||
data->wdt_dev.max_timeout = 0xffffffff / clk_get_rate(data->clk);
|
||||
data->wdt_dev.max_timeout = 0xffffffff / rate;
|
||||
data->wdt_dev.min_timeout = 1;
|
||||
data->wdt_dev.parent = dev;
|
||||
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ static int rzv2h_wdt_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct rzv2h_wdt_priv *priv;
|
||||
struct clk *count_clk;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
@ -314,8 +315,12 @@ static int rzv2h_wdt_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, -EINVAL, "Invalid count source\n");
|
||||
}
|
||||
|
||||
rate = clk_get_rate(count_clk);
|
||||
if (!rate)
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid clock rate\n");
|
||||
|
||||
priv->wdev.max_hw_heartbeat_ms = (MILLI * priv->of_data->timeout_cycles *
|
||||
priv->of_data->cks_div) / clk_get_rate(count_clk);
|
||||
priv->of_data->cks_div) / rate;
|
||||
dev_dbg(dev, "max hw timeout of %dms\n", priv->wdev.max_hw_heartbeat_ms);
|
||||
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
|
|
|
|||
|
|
@ -605,8 +605,10 @@ static int __init sp5100_tco_init(void)
|
|||
pr_info("SP5100/SB800 TCO WatchDog Timer Driver\n");
|
||||
|
||||
err = platform_driver_register(&sp5100_tco_driver);
|
||||
if (err)
|
||||
if (err) {
|
||||
pci_dev_put(sp5100_tco_pci);
|
||||
return err;
|
||||
}
|
||||
|
||||
sp5100_tco_platform_device =
|
||||
platform_device_register_simple(TCO_DRIVER_NAME, -1, NULL, 0);
|
||||
|
|
@ -619,6 +621,7 @@ static int __init sp5100_tco_init(void)
|
|||
|
||||
unreg_platform_driver:
|
||||
platform_driver_unregister(&sp5100_tco_driver);
|
||||
pci_dev_put(sp5100_tco_pci);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -626,6 +629,7 @@ static void __exit sp5100_tco_exit(void)
|
|||
{
|
||||
platform_device_unregister(sp5100_tco_platform_device);
|
||||
platform_driver_unregister(&sp5100_tco_driver);
|
||||
pci_dev_put(sp5100_tco_pci);
|
||||
}
|
||||
|
||||
module_init(sp5100_tco_init);
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ static void starfive_wdt_stop(struct starfive_wdt *wdt)
|
|||
static int starfive_wdt_pm_start(struct watchdog_device *wdd)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
int ret = pm_runtime_get_sync(wdd->parent);
|
||||
int ret = pm_runtime_resume_and_get(wdd->parent);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user