1/* 2 * safe read and write memory routines callable while atomic 3 * 4 * Copyright 2005-2008 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/uaccess.h> 10#include <asm/dma.h> 11 12static int validate_memory_access_address(unsigned long addr, int size) 13{ 14 if (size < 0 || addr == 0) 15 return -EFAULT; 16 return bfin_mem_access_type(addr, size); 17} 18 19long probe_kernel_read(void *dst, void *src, size_t size) 20{ 21 unsigned long lsrc = (unsigned long)src; 22 int mem_type; 23 24 mem_type = validate_memory_access_address(lsrc, size); 25 if (mem_type < 0) 26 return mem_type; 27 28 if (lsrc >= SYSMMR_BASE) { 29 if (size == 2 && lsrc % 2 == 0) { 30 u16 mmr = bfin_read16(src); 31 memcpy(dst, &mmr, sizeof(mmr)); 32 return 0; 33 } else if (size == 4 && lsrc % 4 == 0) { 34 u32 mmr = bfin_read32(src); 35 memcpy(dst, &mmr, sizeof(mmr)); 36 return 0; 37 } 38 } else { 39 switch (mem_type) { 40 case BFIN_MEM_ACCESS_CORE: 41 case BFIN_MEM_ACCESS_CORE_ONLY: 42 return __probe_kernel_read(dst, src, size); 43 case BFIN_MEM_ACCESS_DMA: 44 if (dma_memcpy(dst, src, size)) 45 return 0; 46 break; 47 case BFIN_MEM_ACCESS_ITEST: 48 if (isram_memcpy(dst, src, size)) 49 return 0; 50 break; 51 } 52 } 53 54 return -EFAULT; 55} 56 57long probe_kernel_write(void *dst, void *src, size_t size) 58{ 59 unsigned long ldst = (unsigned long)dst; 60 int mem_type; 61 62 mem_type = validate_memory_access_address(ldst, size); 63 if (mem_type < 0) 64 return mem_type; 65 66 if (ldst >= SYSMMR_BASE) { 67 if (size == 2 && ldst % 2 == 0) { 68 u16 mmr; 69 memcpy(&mmr, src, sizeof(mmr)); 70 bfin_write16(dst, mmr); 71 return 0; 72 } else if (size == 4 && ldst % 4 == 0) { 73 u32 mmr; 74 memcpy(&mmr, src, sizeof(mmr)); 75 bfin_write32(dst, mmr); 76 return 0; 77 } 78 } else { 79 switch (mem_type) { 80 case BFIN_MEM_ACCESS_CORE: 81 case BFIN_MEM_ACCESS_CORE_ONLY: 82 return __probe_kernel_write(dst, src, size); 83 case BFIN_MEM_ACCESS_DMA: 84 if (dma_memcpy(dst, src, size)) 85 return 0; 86 break; 87 case BFIN_MEM_ACCESS_ITEST: 88 if (isram_memcpy(dst, src, size)) 89 return 0; 90 break; 91 } 92 } 93 94 return -EFAULT; 95} 96