mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 01:49:36 +00:00
rtc/mc13783: protect rtc {,un}registration by mc13783 lock
This is to protect from interrupt handlers using an unregistered rtc device. To assert that the reset irq is considered now before the rtc is registered the corresponding status is checked before. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Paul Gortmaker <p_gortmaker@yahoo.com> Cc: Valentin Longchamp <valentin.longchamp@epfl.ch> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Samuel Ortiz <sameo@linux.intel.com> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: Luotao Fu <l.fu@pengutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
86c3400810
commit
4c014e872e
1 changed files with 14 additions and 11 deletions
|
@ -169,6 +169,7 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
|
|||
{
|
||||
int ret;
|
||||
struct mc13783_rtc *priv;
|
||||
int rtcrst_pending;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -177,8 +178,6 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
|
|||
priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->valid = 1;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
|
||||
ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
|
||||
|
@ -186,33 +185,37 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_reset_irq_request;
|
||||
|
||||
ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST,
|
||||
NULL, &rtcrst_pending);
|
||||
if (ret)
|
||||
goto err_reset_irq_status;
|
||||
|
||||
priv->valid = !rtcrst_pending;
|
||||
|
||||
ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
|
||||
mc13783_rtc_update_handler, DRIVER_NAME, priv);
|
||||
if (ret)
|
||||
goto err_update_irq_request;
|
||||
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
priv->rtc = rtc_device_register(pdev->name,
|
||||
&pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(priv->rtc)) {
|
||||
ret = PTR_ERR(priv->rtc);
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
|
||||
mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
|
||||
err_update_irq_request:
|
||||
|
||||
err_reset_irq_status:
|
||||
|
||||
mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
|
||||
err_reset_irq_request:
|
||||
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -220,10 +223,10 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct mc13783_rtc *priv = platform_get_drvdata(pdev);
|
||||
|
||||
rtc_device_unregister(priv->rtc);
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
|
||||
rtc_device_unregister(priv->rtc);
|
||||
|
||||
mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
|
||||
mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
|
||||
|
||||
|
|
Loading…
Reference in a new issue