Root/arch/blackfin/mm/maccess.c

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            /* XXX: should support IDMA here with SMP */
44        case BFIN_MEM_ACCESS_DMA:
45            if (dma_memcpy(dst, src, size))
46                return 0;
47            break;
48        case BFIN_MEM_ACCESS_ITEST:
49            if (isram_memcpy(dst, src, size))
50                return 0;
51            break;
52        }
53    }
54
55    return -EFAULT;
56}
57
58long probe_kernel_write(void *dst, void *src, size_t size)
59{
60    unsigned long ldst = (unsigned long)dst;
61    int mem_type;
62
63    mem_type = validate_memory_access_address(ldst, size);
64    if (mem_type < 0)
65        return mem_type;
66
67    if (ldst >= SYSMMR_BASE) {
68        if (size == 2 && ldst % 2 == 0) {
69            u16 mmr;
70            memcpy(&mmr, src, sizeof(mmr));
71            bfin_write16(dst, mmr);
72            return 0;
73        } else if (size == 4 && ldst % 4 == 0) {
74            u32 mmr;
75            memcpy(&mmr, src, sizeof(mmr));
76            bfin_write32(dst, mmr);
77            return 0;
78        }
79    } else {
80        switch (mem_type) {
81        case BFIN_MEM_ACCESS_CORE:
82        case BFIN_MEM_ACCESS_CORE_ONLY:
83            return __probe_kernel_write(dst, src, size);
84            /* XXX: should support IDMA here with SMP */
85        case BFIN_MEM_ACCESS_DMA:
86            if (dma_memcpy(dst, src, size))
87                return 0;
88            break;
89        case BFIN_MEM_ACCESS_ITEST:
90            if (isram_memcpy(dst, src, size))
91                return 0;
92            break;
93        }
94    }
95
96    return -EFAULT;
97}
98

Archive Download this file



interactive