diff options
-rw-r--r-- | drivers/base/power/runtime.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index cd92e1c77cb7..1244930e3d7a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -348,7 +348,24 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev) | |||
348 | if (!cb) | 348 | if (!cb) |
349 | return -ENOSYS; | 349 | return -ENOSYS; |
350 | 350 | ||
351 | retval = __rpm_callback(cb, dev); | 351 | if (dev->power.memalloc_noio) { |
352 | unsigned int noio_flag; | ||
353 | |||
354 | /* | ||
355 | * Deadlock might be caused if memory allocation with | ||
356 | * GFP_KERNEL happens inside runtime_suspend and | ||
357 | * runtime_resume callbacks of one block device's | ||
358 | * ancestor or the block device itself. Network | ||
359 | * device might be thought as part of iSCSI block | ||
360 | * device, so network device and its ancestor should | ||
361 | * be marked as memalloc_noio too. | ||
362 | */ | ||
363 | noio_flag = memalloc_noio_save(); | ||
364 | retval = __rpm_callback(cb, dev); | ||
365 | memalloc_noio_restore(noio_flag); | ||
366 | } else { | ||
367 | retval = __rpm_callback(cb, dev); | ||
368 | } | ||
352 | 369 | ||
353 | dev->power.runtime_error = retval; | 370 | dev->power.runtime_error = retval; |
354 | return retval != -EACCES ? retval : -EIO; | 371 | return retval != -EACCES ? retval : -EIO; |