MLK-17144 driver: soc: use mutex for power domain of imx8mq
authorBai Ping <ping.bai@nxp.com>
Mon, 11 Dec 2017 04:51:23 +0000 (12:51 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:51:10 +0000 (14:51 -0500)
In current gpc-psci.c file, the irqchip driver and gpc power
domain driver use the same spinlock to prevent concurrent
access to the GPC module. But actually, the irq and power domain
are two seperated function and controlled by different registers.

when using the same spinlock for these two funcition, in some corner
case the system will be deadlock if the spinlock is already acquired
by the power domain, but the power domain on/off is interrupted by
timer IRQ. So adding a mutex for power domain driver.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
drivers/soc/imx/gpc-psci.c

index 49ad145..701a708 100644 (file)
@@ -50,6 +50,7 @@ enum imx_gpc_pm_domain_state {
 #define to_imx_gpc_pm_domain(_genpd) container_of(_genpd, struct imx_gpc_pm_domain, pd)
 
 static DEFINE_SPINLOCK(gpc_psci_lock);
+static DEFINE_MUTEX(gpc_pd_mutex);
 
 static void imx_gpc_psci_irq_unmask(struct irq_data *d)
 {
@@ -216,10 +217,10 @@ static int imx_gpc_pd_power_on(struct generic_pm_domain *domain)
                        clk_prepare_enable(pd->clks[index]);
        }
 
-       spin_lock(&gpc_psci_lock);
+       mutex_lock(&gpc_pd_mutex);
        arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, pd->gpc_domain_id,
                      GPC_PD_STATE_ON, 0, 0, 0, 0, &res);
-       spin_unlock(&gpc_psci_lock);
+       mutex_unlock(&gpc_pd_mutex);
 
        return 0;
 }
@@ -230,10 +231,10 @@ static int imx_gpc_pd_power_off(struct generic_pm_domain *domain)
        struct arm_smccc_res res;
        int index, ret = 0;
 
-       spin_lock(&gpc_psci_lock);
+       mutex_lock(&gpc_pd_mutex);
        arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, pd->gpc_domain_id,
                      GPC_PD_STATE_OFF, 0, 0, 0, 0, &res);
-       spin_unlock(&gpc_psci_lock);
+       mutex_unlock(&gpc_pd_mutex);
 
        /* power off the external supply */
        if (!IS_ERR(pd->reg)) {