ath_procfs.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved.
  3. *
  4. * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  5. *
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for
  8. * any purpose with or without fee is hereby granted, provided that the
  9. * above copyright notice and this permission notice appear in all
  10. * copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  13. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  15. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  16. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  17. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  18. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  19. * PERFORMANCE OF THIS SOFTWARE.
  20. */
  21. /*
  22. * This file was originally distributed by Qualcomm Atheros, Inc.
  23. * under proprietary terms before Copyright ownership was assigned
  24. * to the Linux Foundation.
  25. */
  26. #if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT)
  27. #include <linux/module.h> /* Specifically, a module */
  28. #include <linux/kernel.h> /* We're doing kernel work */
  29. #include <linux/version.h> /* We're doing kernel work */
  30. #include <linux/proc_fs.h> /* Necessary because we use the proc fs */
  31. #include <asm/uaccess.h> /* for copy_from_user */
  32. #include "hif.h"
  33. #if defined(HIF_USB)
  34. #include "if_usb.h"
  35. #endif
  36. #if defined(HIF_SDIO)
  37. #include "if_sdio.h"
  38. #endif
  39. #include "hif_debug.h"
  40. #define PROCFS_NAME "athdiagpfs"
  41. #define PROCFS_DIR "cld"
  42. /**
  43. * This structure hold information about the /proc file
  44. *
  45. */
  46. static struct proc_dir_entry *proc_file, *proc_dir;
  47. static void *get_hif_hdl_from_file(struct file *file)
  48. {
  49. struct hif_opaque_softc *scn;
  50. scn = (struct hif_opaque_softc *)PDE_DATA(file_inode(file));
  51. return (void *)scn;
  52. }
  53. static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf,
  54. size_t count, loff_t *pos)
  55. {
  56. hif_handle_t hif_hdl;
  57. int rv;
  58. uint8_t *read_buffer = NULL;
  59. read_buffer = qdf_mem_malloc(count);
  60. if (NULL == read_buffer) {
  61. HIF_ERROR("%s: cdf_mem_alloc failed", __func__);
  62. return -ENOMEM;
  63. }
  64. hif_hdl = get_hif_hdl_from_file(file);
  65. HIF_DBG("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p",
  66. read_buffer, count, (int)*pos, buf);
  67. if ((count == 4) && ((((uint32_t) (*pos)) & 3) == 0)) {
  68. /* reading a word? */
  69. rv = hif_diag_read_access(hif_hdl, (uint32_t)(*pos),
  70. (uint32_t *)read_buffer);
  71. } else {
  72. rv = hif_diag_read_mem(hif_hdl, (uint32_t)(*pos),
  73. (uint8_t *)read_buffer, count);
  74. }
  75. if (copy_to_user(buf, read_buffer, count)) {
  76. qdf_mem_free(read_buffer);
  77. HIF_ERROR("%s: copy_to_user error in /proc/%s",
  78. __func__, PROCFS_NAME);
  79. return -EFAULT;
  80. } else
  81. qdf_mem_free(read_buffer);
  82. if (rv == 0) {
  83. return count;
  84. } else {
  85. return -EIO;
  86. }
  87. }
  88. static ssize_t ath_procfs_diag_write(struct file *file,
  89. const char __user *buf,
  90. size_t count, loff_t *pos)
  91. {
  92. hif_handle_t hif_hdl;
  93. int rv;
  94. uint8_t *write_buffer = NULL;
  95. write_buffer = qdf_mem_malloc(count);
  96. if (NULL == write_buffer) {
  97. HIF_ERROR("%s: cdf_mem_alloc failed", __func__);
  98. return -ENOMEM;
  99. }
  100. if (copy_from_user(write_buffer, buf, count)) {
  101. qdf_mem_free(write_buffer);
  102. HIF_ERROR("%s: copy_to_user error in /proc/%s",
  103. __func__, PROCFS_NAME);
  104. return -EFAULT;
  105. }
  106. hif_hdl = get_hif_hdl_from_file(file);
  107. HIF_DBG("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x",
  108. write_buffer, buf, count,
  109. (int)*pos, *((uint32_t *) write_buffer));
  110. if ((count == 4) && ((((uint32_t) (*pos)) & 3) == 0)) {
  111. /* reading a word? */
  112. uint32_t value = *((uint32_t *)write_buffer);
  113. rv = hif_diag_write_access(hif_hdl, (uint32_t)(*pos), value);
  114. } else {
  115. rv = hif_diag_write_mem(hif_hdl, (uint32_t)(*pos),
  116. (uint8_t *)write_buffer, count);
  117. }
  118. qdf_mem_free(write_buffer);
  119. if (rv == 0) {
  120. return count;
  121. } else {
  122. return -EIO;
  123. }
  124. }
  125. static const struct file_operations athdiag_fops = {
  126. .read = ath_procfs_diag_read,
  127. .write = ath_procfs_diag_write,
  128. };
  129. /**
  130. *This function is called when the module is loaded
  131. *
  132. */
  133. int athdiag_procfs_init(void *scn)
  134. {
  135. proc_dir = proc_mkdir(PROCFS_DIR, NULL);
  136. if (proc_dir == NULL) {
  137. remove_proc_entry(PROCFS_DIR, NULL);
  138. HIF_ERROR("%s: Error: Could not initialize /proc/%s",
  139. __func__, PROCFS_DIR);
  140. return -ENOMEM;
  141. }
  142. proc_file = proc_create_data(PROCFS_NAME,
  143. S_IRUSR | S_IWUSR, proc_dir,
  144. &athdiag_fops, (void *)scn);
  145. if (proc_file == NULL) {
  146. remove_proc_entry(PROCFS_NAME, proc_dir);
  147. HIF_ERROR("%s: Could not initialize /proc/%s",
  148. __func__, PROCFS_NAME);
  149. return -ENOMEM;
  150. }
  151. HIF_DBG("/proc/%s/%s created", PROCFS_DIR, PROCFS_NAME);
  152. return 0; /* everything is ok */
  153. }
  154. /**
  155. *This function is called when the module is unloaded
  156. *
  157. */
  158. void athdiag_procfs_remove(void)
  159. {
  160. if (proc_dir != NULL) {
  161. remove_proc_entry(PROCFS_NAME, proc_dir);
  162. HIF_DBG("/proc/%s/%s removed", PROCFS_DIR, PROCFS_NAME);
  163. remove_proc_entry(PROCFS_DIR, NULL);
  164. HIF_DBG("/proc/%s removed", PROCFS_DIR);
  165. proc_dir = NULL;
  166. }
  167. }
  168. #else
  169. int athdiag_procfs_init(void *scn)
  170. {
  171. return 0;
  172. }
  173. void athdiag_procfs_remove(void) {}
  174. #endif