aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2010-03-05 16:44:30 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-06 14:26:47 -0500
commit4c014e872e02baa5b0bde38b2b2867ccf1f9df76 (patch)
treeb9e6315145e8c50b684ce532696a2082c90a987a
parent86c3400810a7a33e176bf33b6b074d881e829374 (diff)
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>
-rw-r--r--drivers/rtc/rtc-mc13783.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
index 0a978a0e40fc..6a36201178a8 100644
--- a/drivers/rtc/rtc-mc13783.c
+++ b/drivers/rtc/rtc-mc13783.c
@@ -169,6 +169,7 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
169{ 169{
170 int ret; 170 int ret;
171 struct mc13783_rtc *priv; 171 struct mc13783_rtc *priv;
172 int rtcrst_pending;
172 173
173 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 174 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
174 if (!priv) 175 if (!priv)
@@ -177,8 +178,6 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
177 priv->mc13783 = dev_get_drvdata(pdev->dev.parent); 178 priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
178 platform_set_drvdata(pdev, priv); 179 platform_set_drvdata(pdev, priv);
179 180
180 priv->valid = 1;
181
182 mc13783_lock(priv->mc13783); 181 mc13783_lock(priv->mc13783);
183 182
184 ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, 183 ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
@@ -186,33 +185,37 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
186 if (ret) 185 if (ret)
187 goto err_reset_irq_request; 186 goto err_reset_irq_request;
188 187
188 ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST,
189 NULL, &rtcrst_pending);
190 if (ret)
191 goto err_reset_irq_status;
192
193 priv->valid = !rtcrst_pending;
194
189 ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, 195 ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
190 mc13783_rtc_update_handler, DRIVER_NAME, priv); 196 mc13783_rtc_update_handler, DRIVER_NAME, priv);
191 if (ret) 197 if (ret)
192 goto err_update_irq_request; 198 goto err_update_irq_request;
193 199
194 mc13783_unlock(priv->mc13783);
195
196 priv->rtc = rtc_device_register(pdev->name, 200 priv->rtc = rtc_device_register(pdev->name,
197 &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); 201 &pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
198
199 if (IS_ERR(priv->rtc)) { 202 if (IS_ERR(priv->rtc)) {
200 ret = PTR_ERR(priv->rtc); 203 ret = PTR_ERR(priv->rtc);
201 204
202 mc13783_lock(priv->mc13783);
203
204 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); 205 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
205err_update_irq_request: 206err_update_irq_request:
206 207
208err_reset_irq_status:
209
207 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); 210 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
208err_reset_irq_request: 211err_reset_irq_request:
209 212
210 mc13783_unlock(priv->mc13783);
211
212 platform_set_drvdata(pdev, NULL); 213 platform_set_drvdata(pdev, NULL);
213 kfree(priv); 214 kfree(priv);
214 } 215 }
215 216
217 mc13783_unlock(priv->mc13783);
218
216 return ret; 219 return ret;
217} 220}
218 221
@@ -220,10 +223,10 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
220{ 223{
221 struct mc13783_rtc *priv = platform_get_drvdata(pdev); 224 struct mc13783_rtc *priv = platform_get_drvdata(pdev);
222 225
223 rtc_device_unregister(priv->rtc);
224
225 mc13783_lock(priv->mc13783); 226 mc13783_lock(priv->mc13783);
226 227
228 rtc_device_unregister(priv->rtc);
229
227 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); 230 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
228 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); 231 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
229 232