#ifdef CONFIG_S3C2410_PM_CHECK
 extern void s3c_pm_check_prepare(void);
 extern void s3c_pm_check_restore(void);
+extern void s3c_pm_check_cleanup(void);
 extern void s3c_pm_check_store(void);
 #else
 #define s3c_pm_check_prepare() do { } while(0)
 #define s3c_pm_check_restore() do { } while(0)
+#define s3c_pm_check_cleanup() do { } while(0)
 #define s3c_pm_check_store()   do { } while(0)
 #endif
 
 
 */
 void s3c_pm_check_restore(void)
 {
-       if (crcs != NULL) {
+       if (crcs != NULL)
                s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
-               kfree(crcs);
-               crcs = NULL;
-       }
 }
+
+/**
+ * s3c_pm_check_cleanup() - free memory resources
+ *
+ * Free the resources that where allocated by the suspend
+ * memory check code. We do this separately from the
+ * s3c_pm_check_restore() function as we cannot call any
+ * functions that might sleep during that resume.
+ */
+void s3c_pm_check_cleanup(void)
+{
+       kfree(crcs);
+       crcs = NULL;
+}
+
 
                return -EINVAL;
        }
 
-       /* prepare check area if configured */
-
-       s3c_pm_check_prepare();
-
        /* store the physical address of the register recovery block */
 
        s3c_sleep_save_phys = virt_to_phys(regs_save);
        return 0;
 }
 
+static int s3c_pm_prepare(void)
+{
+       /* prepare check area if configured */
+
+       s3c_pm_check_prepare();
+       return 0;
+}
+
+static void s3c_pm_finish(void)
+{
+       s3c_pm_check_cleanup();
+}
+
 static struct platform_suspend_ops s3c_pm_ops = {
        .enter          = s3c_pm_enter,
+       .prepare        = s3c_pm_prepare,
+       .finish         = s3c_pm_finish,
        .valid          = suspend_valid_only_mem,
 };