tegra-alt: adsp: schedule work for freq override
Viraj Karandikar [Wed, 31 Aug 2016 12:23:14 +0000 (17:23 +0530)]
Schedule worker function for frequency override to avoid
adsp_override_freq() and clk_set_rate() getting called
from atomic context.

Bug 200222934

Change-Id: Ia65ce4a617bfd4494d04bdfac8b28e6d8260943c
Signed-off-by: Viraj Karandikar <vkarandikar@nvidia.com>
Reviewed-on: http://git-master/r/1211239
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Puneet Saxena <puneets@nvidia.com>
Reviewed-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>

sound/soc/tegra-alt/tegra210_adsp_alt.c

index 3b5f97b..ad8528c 100644 (file)
@@ -95,6 +95,7 @@ struct tegra210_adsp_app {
        spinlock_t lock;
        void *private_data;
        int (*msg_handler)(struct tegra210_adsp_app *, apm_msg_t *);
+       struct work_struct *override_freq_work;
 };
 
 struct tegra210_adsp_pcm_rtd {
@@ -117,6 +118,7 @@ struct tegra210_adsp {
        struct tegra210_adsp_app apps[TEGRA210_ADSP_VIRT_REG_MAX];
        atomic_t reg_val[TEGRA210_ADSP_VIRT_REG_MAX];
        DECLARE_BITMAP(adma_usage, TEGRA210_ADSP_ADMA_CHANNEL_COUNT);
+       struct work_struct override_freq_work;
        uint32_t i2s_rate;
        struct mutex mutex;
        int init_done;
@@ -566,6 +568,11 @@ static int tegra210_adsp_adma_params_msg(struct tegra210_adsp_app *app,
        return tegra210_adsp_send_msg(app, &apm_msg, flags);
 }
 
+static void tegra_adsp_override_freq_worker(struct work_struct *work)
+{
+       adsp_override_freq(INT_MAX);
+}
+
 static int tegra210_adsp_send_state_msg(struct tegra210_adsp_app *app,
                                        int32_t state, uint32_t flags)
 {
@@ -579,7 +586,7 @@ static int tegra210_adsp_send_state_msg(struct tegra210_adsp_app *app,
        /* Spike ADSP freq to max when app transitions to active */
        /* state; DFS will thereafter find appropriate rate      */
        if (state == nvfx_state_active)
-               adsp_override_freq(INT_MAX);
+               schedule_work(app->override_freq_work);
 
        return tegra210_adsp_send_msg(app, &apm_msg, flags);
 }
@@ -663,6 +670,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
 
        app->adsp = adsp;
        app->msg_handler = tegra210_adsp_app_default_msg_handler;
+       app->override_freq_work = &adsp->override_freq_work;
        app->plugin = PLUGIN_SHARED_MEM(app->info->mem.shared);
        if (IS_APM_IN(app->reg)) {
                uint32_t apm_out_reg = APM_OUT_START +
@@ -2848,6 +2856,7 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
        adsp->i2s_rate = 48000;
        adsp->recovery_enabled = 0;
        adsp->recovery_count = 0;
+       INIT_WORK(&adsp->override_freq_work, tegra_adsp_override_freq_worker);
        mutex_init(&adsp->mutex);
        pdev->dev.dma_mask = &tegra_dma_mask;
        pdev->dev.coherent_dma_mask = tegra_dma_mask;