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