gpu: pvr: fix locking on the HW recovery reset error path
[sgx.git] / pvr / sysutils.c
index 79e1c87..33a8057 100644 (file)
@@ -41,6 +41,7 @@
 #include "syslocal.h"
 #include "env_data.h"
 #include "ocpdefs.h"
+#include "pvr_bridge_km.h"
 
 #define        HZ_TO_MHZ(m) ((m) / 1000000)
 
@@ -90,7 +91,7 @@ static int vdd2_post_func(struct notifier_block *n, unsigned long event,
 
        if (atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0 &&
            gpsSysSpecificData->bSGXInitComplete) {
-#if defined(DEBUG)
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
                unsigned long rate;
 
                rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
@@ -143,16 +144,16 @@ static int vdd2_pre_post_func(struct notifier_block *n, unsigned long event,
                  cnd->rate);
 
        if (CLK_PRE_RATE_CHANGE == event) {
-               PVRSRVDvfsLock();
+               pvr_dev_lock();
                PVR_TRACE("vdd2_pre_post_func: CLK_PRE_RATE_CHANGE event");
                vdd2_pre_func(n, event, ptr);
        } else if (CLK_POST_RATE_CHANGE == event) {
                PVR_TRACE("vdd2_pre_post_func: CLK_POST_RATE_CHANGE event");
                vdd2_post_func(n, event, ptr);
-               PVRSRVDvfsUnlock();
+               pvr_dev_unlock();
        } else if (CLK_ABORT_RATE_CHANGE == event) {
                PVR_TRACE("vdd2_pre_post_func: CLK_ABORT_RATE_CHANGE event");
-               PVRSRVDvfsUnlock();
+               pvr_dev_unlock();
        } else {
                printk(KERN_ERR "vdd2_pre_post_func: unexpected event (%lu)\n",
                        event);
@@ -265,7 +266,17 @@ static void sgx_lock_perf(struct work_struct *work)
        struct ENV_DATA *psEnvData =
            container_of(d_work, struct ENV_DATA, sPerfWork);
 
+       pvr_lock();
+
+       if (pvr_is_disabled()) {
+               pvr_unlock();
+               return;
+       }
+
        load = sgx_current_load();
+
+       pvr_unlock();
+
        if (load) {
                vdd1 = 500000000;
                vdd2 = 400000;
@@ -454,6 +465,8 @@ static enum PVRSRV_ERROR InitSgxClocks(struct SYS_DATA *psSysData)
        struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
        struct clk *psCLK;
        struct clk *core_ck = NULL;
+       unsigned long rate;
+       int r;
 
        psCLK = clk_get(NULL, "sgx_fck");
        if (IS_ERR(psCLK))
@@ -474,6 +487,19 @@ static enum PVRSRV_ERROR InitSgxClocks(struct SYS_DATA *psSysData)
        }
        clk_put(core_ck);
 
+       /* +1 to account for rounding errors */
+       rate = clk_round_rate(psSysSpecData->psSGX_FCK, sgx_get_max_freq() + 1);
+       r = clk_set_rate(psSysSpecData->psSGX_FCK, rate);
+       if (r < 0) {
+               unsigned long current_rate;
+
+               current_rate = clk_get_rate(psSysSpecData->psSGX_FCK);
+               pr_warning("error %d when setting SGX fclk to %lu Hz, "
+                          "falling back to %lu Hz\n", r, rate, current_rate);
+       } else {
+               pr_info("SGX clock rate %lu MHz\n", rate / 1000000);
+       };
+
        RegisterConstraintNotifications(psSysSpecData);
        return PVRSRV_OK;
 
@@ -507,7 +533,7 @@ static void CleanupSgxClocks(struct SYS_DATA *psSysData)
        }
 }
 
-#if defined(DEBUG) || defined(TIMING)
+#if defined(CONFIG_PVR_DEBUG_EXTRA) || defined(TIMING)
 static inline u32 gpt_read_reg(struct SYS_DATA *psSysData, u32 reg)
 {
        struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;