aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2014-01-08 02:15:33 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-21 03:29:01 -0500
commit76a0775d46da052f123b8598a3dfc3b330b8de4f (patch)
tree87888ffb32af1071d1e242ff43dc7848a03edbb0
parent3b1ba0cbcc1bc16b39dbd6cc4585a1d365f351f3 (diff)
mfd: omap-usb-tll: Don't hold lock during pm_runtime_get/put_sync()
pm_runtime_get/put_sync() can sleep so don't hold spinlock while calling them. This patch prevents a BUG() during system suspend when CONFIG_DEBUG_ATOMIC_SLEEP is enabled. Bug is present in Kernel versions v3.9 onwards. Reported-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Roger Quadros <rogerq@ti.com> Tested-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/omap-usb-tll.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index ee7468c1cb60..5ee50f779ef6 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -333,21 +333,17 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
333 unsigned reg; 333 unsigned reg;
334 struct usbtll_omap *tll; 334 struct usbtll_omap *tll;
335 335
336 spin_lock(&tll_lock); 336 if (!tll_dev)
337
338 if (!tll_dev) {
339 spin_unlock(&tll_lock);
340 return -ENODEV; 337 return -ENODEV;
341 }
342 338
343 tll = dev_get_drvdata(tll_dev); 339 pm_runtime_get_sync(tll_dev);
344 340
341 spin_lock(&tll_lock);
342 tll = dev_get_drvdata(tll_dev);
345 needs_tll = false; 343 needs_tll = false;
346 for (i = 0; i < tll->nch; i++) 344 for (i = 0; i < tll->nch; i++)
347 needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]); 345 needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
348 346
349 pm_runtime_get_sync(tll_dev);
350
351 if (needs_tll) { 347 if (needs_tll) {
352 void __iomem *base = tll->base; 348 void __iomem *base = tll->base;
353 349
@@ -398,9 +394,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
398 } 394 }
399 } 395 }
400 396
401 pm_runtime_put_sync(tll_dev);
402
403 spin_unlock(&tll_lock); 397 spin_unlock(&tll_lock);
398 pm_runtime_put_sync(tll_dev);
404 399
405 return 0; 400 return 0;
406} 401}
@@ -411,17 +406,14 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
411 int i; 406 int i;
412 struct usbtll_omap *tll; 407 struct usbtll_omap *tll;
413 408
414 spin_lock(&tll_lock); 409 if (!tll_dev)
415
416 if (!tll_dev) {
417 spin_unlock(&tll_lock);
418 return -ENODEV; 410 return -ENODEV;
419 }
420
421 tll = dev_get_drvdata(tll_dev);
422 411
423 pm_runtime_get_sync(tll_dev); 412 pm_runtime_get_sync(tll_dev);
424 413
414 spin_lock(&tll_lock);
415 tll = dev_get_drvdata(tll_dev);
416
425 for (i = 0; i < tll->nch; i++) { 417 for (i = 0; i < tll->nch; i++) {
426 if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { 418 if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
427 int r; 419 int r;
@@ -448,13 +440,10 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
448 int i; 440 int i;
449 struct usbtll_omap *tll; 441 struct usbtll_omap *tll;
450 442
451 spin_lock(&tll_lock); 443 if (!tll_dev)
452
453 if (!tll_dev) {
454 spin_unlock(&tll_lock);
455 return -ENODEV; 444 return -ENODEV;
456 }
457 445
446 spin_lock(&tll_lock);
458 tll = dev_get_drvdata(tll_dev); 447 tll = dev_get_drvdata(tll_dev);
459 448
460 for (i = 0; i < tll->nch; i++) { 449 for (i = 0; i < tll->nch; i++) {
@@ -464,9 +453,8 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
464 } 453 }
465 } 454 }
466 455
467 pm_runtime_put_sync(tll_dev);
468
469 spin_unlock(&tll_lock); 456 spin_unlock(&tll_lock);
457 pm_runtime_put_sync(tll_dev);
470 458
471 return 0; 459 return 0;
472} 460}