1 /* 2 * Support for atomisp driver sysfs interface 3 * 4 * Copyright (c) 2014 Intel Corporation. All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License version 8 * 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * 16 */ 17 18 #include <linux/device.h> 19 #include <linux/err.h> 20 #include <linux/kernel.h> 21 22 #include "atomisp_compat.h" 23 #include "atomisp_internal.h" 24 #include "atomisp_ioctl.h" 25 #include "atomisp_drvfs.h" 26 #include "hmm/hmm.h" 27 #include "ia_css_debug.h" 28 29 /* 30 * _iunit_debug: 31 * dbglvl: iunit css driver trace level 32 * dbgopt: iunit debug option: 33 * bit 0: binary list 34 * bit 1: running binary 35 * bit 2: memory statistic 36 */ 37 struct _iunit_debug { 38 struct device_driver *drv; 39 struct atomisp_device *isp; 40 unsigned int dbglvl; 41 unsigned int dbgfun; 42 unsigned int dbgopt; 43 }; 44 45 #define OPTION_BIN_LIST BIT(0) 46 #define OPTION_BIN_RUN BIT(1) 47 #define OPTION_MEM_STAT BIT(2) 48 #define OPTION_VALID (OPTION_BIN_LIST \ 49 | OPTION_BIN_RUN \ 50 | OPTION_MEM_STAT) 51 52 static struct _iunit_debug iunit_debug = { 53 .dbglvl = 0, 54 .dbgopt = OPTION_BIN_LIST, 55 }; 56 57 static inline int iunit_dump_dbgopt(struct atomisp_device *isp, 58 unsigned int opt) 59 { 60 int ret = 0; 61 62 if (opt & OPTION_VALID) { 63 if (opt & OPTION_BIN_LIST) { 64 ret = atomisp_css_dump_blob_infor(); 65 if (ret) { 66 dev_err(atomisp_dev, "%s dump blob infor err[ret:%d]\n", 67 __func__, ret); 68 goto opt_err; 69 } 70 } 71 72 if (opt & OPTION_BIN_RUN) { 73 if (atomisp_streaming_count(isp)) { 74 atomisp_css_dump_sp_raw_copy_linecount(true); 75 atomisp_css_debug_dump_isp_binary(); 76 } else { 77 ret = -EPERM; 78 dev_err(atomisp_dev, "%s dump running bin err[ret:%d]\n", 79 __func__, ret); 80 goto opt_err; 81 } 82 } 83 84 if (opt & OPTION_MEM_STAT) 85 hmm_show_mem_stat(__func__, __LINE__); 86 } else { 87 ret = -EINVAL; 88 dev_err(atomisp_dev, "%s dump nothing[ret=%d]\n", __func__, 89 ret); 90 } 91 92 opt_err: 93 return ret; 94 } 95 96 static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf) 97 { 98 iunit_debug.dbglvl = dbg_level; 99 return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl); 100 } 101 102 static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf, 103 size_t size) 104 { 105 if (kstrtouint(buf, 10, &iunit_debug.dbglvl) 106 || iunit_debug.dbglvl < 1 107 || iunit_debug.dbglvl > 9) { 108 return -ERANGE; 109 } 110 ia_css_debug_set_dtrace_level(iunit_debug.dbglvl); 111 112 return size; 113 } 114 115 static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf) 116 { 117 iunit_debug.dbgfun = atomisp_get_css_dbgfunc(); 118 return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun); 119 } 120 121 static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf, 122 size_t size) 123 { 124 unsigned int opt; 125 int ret; 126 127 ret = kstrtouint(buf, 10, &opt); 128 if (ret) 129 return ret; 130 131 ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt); 132 if (ret) 133 return ret; 134 135 iunit_debug.dbgfun = opt; 136 137 return size; 138 } 139 140 static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf) 141 { 142 return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt); 143 } 144 145 static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf, 146 size_t size) 147 { 148 unsigned int opt; 149 int ret; 150 151 ret = kstrtouint(buf, 10, &opt); 152 if (ret) 153 return ret; 154 155 iunit_debug.dbgopt = opt; 156 ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt); 157 if (ret) 158 return ret; 159 160 return size; 161 } 162 163 static const struct driver_attribute iunit_drvfs_attrs[] = { 164 __ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store), 165 __ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store), 166 __ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store), 167 }; 168 169 static int iunit_drvfs_create_files(struct device_driver *drv) 170 { 171 int i, ret = 0; 172 173 for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++) 174 ret |= driver_create_file(drv, &iunit_drvfs_attrs[i]); 175 176 return ret; 177 } 178 179 static void iunit_drvfs_remove_files(struct device_driver *drv) 180 { 181 int i; 182 183 for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++) 184 driver_remove_file(drv, &iunit_drvfs_attrs[i]); 185 } 186 187 int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp) 188 { 189 int ret; 190 191 iunit_debug.isp = isp; 192 iunit_debug.drv = drv; 193 194 ret = iunit_drvfs_create_files(iunit_debug.drv); 195 if (ret) { 196 dev_err(atomisp_dev, "drvfs_create_files error: %d\n", ret); 197 iunit_drvfs_remove_files(iunit_debug.drv); 198 } 199 200 return ret; 201 } 202 203 void atomisp_drvfs_exit(void) 204 { 205 iunit_drvfs_remove_files(iunit_debug.drv); 206 } 207