maccess.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. #include <linux/uaccess.h>
  9. #include <asm/dma.h>
  10. static int validate_memory_access_address(unsigned long addr, int size)
  11. {
  12. if (size < 0 || addr == 0)
  13. return -EFAULT;
  14. return bfin_mem_access_type(addr, size);
  15. }
  16. long probe_kernel_read(void *dst, const void *src, size_t size)
  17. {
  18. unsigned long lsrc = (unsigned long)src;
  19. int mem_type;
  20. mem_type = validate_memory_access_address(lsrc, size);
  21. if (mem_type < 0)
  22. return mem_type;
  23. if (lsrc >= SYSMMR_BASE) {
  24. if (size == 2 && lsrc % 2 == 0) {
  25. u16 mmr = bfin_read16(src);
  26. memcpy(dst, &mmr, sizeof(mmr));
  27. return 0;
  28. } else if (size == 4 && lsrc % 4 == 0) {
  29. u32 mmr = bfin_read32(src);
  30. memcpy(dst, &mmr, sizeof(mmr));
  31. return 0;
  32. }
  33. } else {
  34. switch (mem_type) {
  35. case BFIN_MEM_ACCESS_CORE:
  36. case BFIN_MEM_ACCESS_CORE_ONLY:
  37. return __probe_kernel_read(dst, src, size);
  38. /* XXX: should support IDMA here with SMP */
  39. case BFIN_MEM_ACCESS_DMA:
  40. if (dma_memcpy(dst, src, size))
  41. return 0;
  42. break;
  43. case BFIN_MEM_ACCESS_ITEST:
  44. if (isram_memcpy(dst, src, size))
  45. return 0;
  46. break;
  47. }
  48. }
  49. return -EFAULT;
  50. }
  51. long probe_kernel_write(void *dst, const void *src, size_t size)
  52. {
  53. unsigned long ldst = (unsigned long)dst;
  54. int mem_type;
  55. mem_type = validate_memory_access_address(ldst, size);
  56. if (mem_type < 0)
  57. return mem_type;
  58. if (ldst >= SYSMMR_BASE) {
  59. if (size == 2 && ldst % 2 == 0) {
  60. u16 mmr;
  61. memcpy(&mmr, src, sizeof(mmr));
  62. bfin_write16(dst, mmr);
  63. return 0;
  64. } else if (size == 4 && ldst % 4 == 0) {
  65. u32 mmr;
  66. memcpy(&mmr, src, sizeof(mmr));
  67. bfin_write32(dst, mmr);
  68. return 0;
  69. }
  70. } else {
  71. switch (mem_type) {
  72. case BFIN_MEM_ACCESS_CORE:
  73. case BFIN_MEM_ACCESS_CORE_ONLY:
  74. return __probe_kernel_write(dst, src, size);
  75. /* XXX: should support IDMA here with SMP */
  76. case BFIN_MEM_ACCESS_DMA:
  77. if (dma_memcpy(dst, src, size))
  78. return 0;
  79. break;
  80. case BFIN_MEM_ACCESS_ITEST:
  81. if (isram_memcpy(dst, src, size))
  82. return 0;
  83. break;
  84. }
  85. }
  86. return -EFAULT;
  87. }