Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // originally in linux/arch/arm/plat-s3c24xx/pm.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) // Copyright (c) 2004-2008 Simtec Electronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) //	http://armlinux.simtec.co.uk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) //	Ben Dooks <ben@simtec.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) // S3C Power Mangament - suspend/resume memory corruption check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/soc/samsung/s3c-pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #if CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE < 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #error CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE must be a positive non-zero value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /* suspend checking code...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * this next area does a set of crc checks over all the installed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * memory, so the system can verify if the resume was ok.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * increasing it will mean that the area corrupted will be less easy to spot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * and reducing the size will cause the CRC save area to grow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define CHECK_CHUNKSIZE (CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static u32 crc_size;	/* size needed for the crc block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static u32 *crcs;	/* allocated over suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) /* s3c_pm_run_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * go through the given resource list, and look for system ram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	while (ptr != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		if (ptr->child != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			s3c_pm_run_res(ptr->child, fn, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		if ((ptr->flags & IORESOURCE_SYSTEM_RAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 				== IORESOURCE_SYSTEM_RAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 				  (unsigned long)ptr->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 				  (unsigned long)ptr->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			arg = (fn)(ptr, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		ptr = ptr->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	s3c_pm_run_res(&iomem_resource, fn, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static u32 *s3c_pm_countram(struct resource *res, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	u32 size = (u32)resource_size(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	size += CHECK_CHUNKSIZE-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	size /= CHECK_CHUNKSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		  (unsigned long)res->start, (unsigned long)res->end, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	*val += size * sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) /* s3c_pm_prepare_check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * prepare the necessary information for creating the CRCs. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * must be done before the final save, as it will require memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * allocating, and thus touching bits of the kernel we do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * know about.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) void s3c_pm_check_prepare(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	crc_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	crcs = kmalloc(crc_size+4, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (crcs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		printk(KERN_ERR "Cannot allocated CRC save area\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	unsigned long addr, left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	for (addr = res->start; addr < res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	     addr += CHECK_CHUNKSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		left = res->end - addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		if (left > CHECK_CHUNKSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			left = CHECK_CHUNKSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		*val = crc32_le(~0, phys_to_virt(addr), left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* s3c_pm_check_store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * compute the CRC values for the memory blocks before the final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void s3c_pm_check_store(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (crcs != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* in_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  * return TRUE if the area defined by ptr..ptr+size contains the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  * what..what+whatsz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if ((what+whatsz) < ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	if (what > (ptr+size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * s3c_pm_runcheck() - helper to check a resource on restore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * @res: The resource to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * @vak: Pointer to list of CRC32 values to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * function runs the given memory resource checking it against the stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  * CRC to ensure that memory is restored. The function tries to skip as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  * many of the areas used during the suspend process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	unsigned long left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	void *stkpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	u32 calc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	stkpage = (void *)((u32)&calc & ~PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	for (addr = res->start; addr < res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	     addr += CHECK_CHUNKSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		left = res->end - addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		if (left > CHECK_CHUNKSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			left = CHECK_CHUNKSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		ptr = phys_to_virt(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		if (in_region(ptr, left, stkpage, 4096)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			S3C_PMDBG("skipping %08lx, has stack in\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			goto skip_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		if (in_region(ptr, left, crcs, crc_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			goto skip_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		/* calculate and check the checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		calc = crc32_le(~0, ptr, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		if (calc != *val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			printk(KERN_ERR "Restore CRC error at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			    addr, calc, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	skip_check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * s3c_pm_check_restore() - memory check called on resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * check the CRCs after the restore event and free the memory used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * to hold them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) void s3c_pm_check_restore(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	if (crcs != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  * s3c_pm_check_cleanup() - free memory resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * Free the resources that where allocated by the suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  * memory check code. We do this separately from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * s3c_pm_check_restore() function as we cannot call any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  * functions that might sleep during that resume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void s3c_pm_check_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	kfree(crcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	crcs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)