mmc: core: Use PF_MEMALLOC flag for clock scaling context

Memory allocations with GFP_KERNEL flag in clock scaling path might
trigger IO transfer. This can cause deadlock since the claim_host
lock which is needed by mmc driver to perform IO is held by clock
scaling context.

Below is the exact call sequence:

mmc_devfreq_set_target() -> mmc_clk_update_freq () ->
mmc_change_bus_speed() -> mmc_select_hs400() -> mmc_select_bus_width()
-> mmc_get_ext_csd() -> kzalloc(512, GFP_KERNEL) -> try_to_free_pages()
-> evict() -> ext4_evict_inode().

To avoid this scenario, use PF_MEMALLOC flag for clock scaling context
so that it can have access to the more reserves of memory. And since
devfreq workitem would run in different kworker threads, restore to
original flags once done with setting clock frequency.

Change-Id: If52f83f6ecae982d8ed709b08fd84545c7ecbc43
Signed-off-by: Veerabhadrarao Badiganti <vbadigan@codeaurora.org>
This commit is contained in:
Veerabhadrarao Badiganti 2017-06-23 19:18:45 +05:30
parent e5b8aadd07
commit 1fbefb5219

View file

@ -487,12 +487,17 @@ static int mmc_devfreq_set_target(struct device *dev,
struct mmc_devfeq_clk_scaling *clk_scaling;
int err = 0;
int abort;
unsigned long pflags = current->flags;
/* Ensure scaling would happen even in memory pressure conditions */
current->flags |= PF_MEMALLOC;
if (!(host && freq)) {
pr_err("%s: unexpected host/freq parameter\n", __func__);
err = -EINVAL;
goto out;
}
clk_scaling = &host->clk_scaling;
if (!clk_scaling->enable)
@ -551,6 +556,7 @@ static int mmc_devfreq_set_target(struct device *dev,
rel_host:
mmc_release_host(host);
out:
tsk_restore_flags(current, pflags, PF_MEMALLOC);
return err;
}