Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c014e87 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Linus Torvalds
Browse files

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: default avatarUwe 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 86c34008
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -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);