// SPDX-License-Identifier: GPL-2.0
|
/*
|
* Support for atomisp driver sysfs interface
|
*
|
* Copyright (c) 2014 Intel Corporation. All Rights Reserved.
|
*
|
* This program is free software; you can redistribute it and/or
|
* modify it under the terms of the GNU General Public License version
|
* 2 as published by the Free Software Foundation.
|
*
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
*
|
*
|
*/
|
|
#include <linux/device.h>
|
#include <linux/err.h>
|
#include <linux/kernel.h>
|
|
#include "atomisp_compat.h"
|
#include "atomisp_internal.h"
|
#include "atomisp_ioctl.h"
|
#include "atomisp_drvfs.h"
|
#include "hmm/hmm.h"
|
#include "ia_css_debug.h"
|
|
/*
|
* _iunit_debug:
|
* dbglvl: iunit css driver trace level
|
* dbgopt: iunit debug option:
|
* bit 0: binary list
|
* bit 1: running binary
|
* bit 2: memory statistic
|
*/
|
struct _iunit_debug {
|
struct device_driver *drv;
|
struct atomisp_device *isp;
|
unsigned int dbglvl;
|
unsigned int dbgfun;
|
unsigned int dbgopt;
|
};
|
|
#define OPTION_BIN_LIST BIT(0)
|
#define OPTION_BIN_RUN BIT(1)
|
#define OPTION_MEM_STAT BIT(2)
|
#define OPTION_VALID (OPTION_BIN_LIST \
|
| OPTION_BIN_RUN \
|
| OPTION_MEM_STAT)
|
|
static struct _iunit_debug iunit_debug = {
|
.dbglvl = 0,
|
.dbgopt = OPTION_BIN_LIST,
|
};
|
|
static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
|
unsigned int opt)
|
{
|
int ret = 0;
|
|
if (opt & OPTION_VALID) {
|
if (opt & OPTION_BIN_LIST) {
|
ret = atomisp_css_dump_blob_infor(isp);
|
if (ret) {
|
dev_err(isp->dev, "%s dump blob infor err[ret:%d]\n",
|
__func__, ret);
|
goto opt_err;
|
}
|
}
|
|
if (opt & OPTION_BIN_RUN) {
|
if (atomisp_streaming_count(isp)) {
|
atomisp_css_dump_sp_raw_copy_linecount(true);
|
atomisp_css_debug_dump_isp_binary();
|
} else {
|
ret = -EPERM;
|
dev_err(isp->dev, "%s dump running bin err[ret:%d]\n",
|
__func__, ret);
|
goto opt_err;
|
}
|
}
|
|
if (opt & OPTION_MEM_STAT)
|
hmm_show_mem_stat(__func__, __LINE__);
|
} else {
|
ret = -EINVAL;
|
dev_err(isp->dev, "%s dump nothing[ret=%d]\n", __func__, ret);
|
}
|
|
opt_err:
|
return ret;
|
}
|
|
static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
|
{
|
iunit_debug.dbglvl = dbg_level;
|
return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
|
}
|
|
static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
|
size_t size)
|
{
|
if (kstrtouint(buf, 10, &iunit_debug.dbglvl)
|
|| iunit_debug.dbglvl < 1
|
|| iunit_debug.dbglvl > 9) {
|
return -ERANGE;
|
}
|
ia_css_debug_set_dtrace_level(iunit_debug.dbglvl);
|
|
return size;
|
}
|
|
static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
|
{
|
iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
|
return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
|
}
|
|
static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
|
size_t size)
|
{
|
unsigned int opt;
|
int ret;
|
|
ret = kstrtouint(buf, 10, &opt);
|
if (ret)
|
return ret;
|
|
ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt);
|
if (ret)
|
return ret;
|
|
iunit_debug.dbgfun = opt;
|
|
return size;
|
}
|
|
static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
|
{
|
return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt);
|
}
|
|
static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
|
size_t size)
|
{
|
unsigned int opt;
|
int ret;
|
|
ret = kstrtouint(buf, 10, &opt);
|
if (ret)
|
return ret;
|
|
iunit_debug.dbgopt = opt;
|
ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt);
|
if (ret)
|
return ret;
|
|
return size;
|
}
|
|
static const struct driver_attribute iunit_drvfs_attrs[] = {
|
__ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store),
|
__ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store),
|
__ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store),
|
};
|
|
static int iunit_drvfs_create_files(struct device_driver *drv)
|
{
|
int i, ret = 0;
|
|
for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
|
ret |= driver_create_file(drv, &iunit_drvfs_attrs[i]);
|
|
return ret;
|
}
|
|
static void iunit_drvfs_remove_files(struct device_driver *drv)
|
{
|
int i;
|
|
for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
|
driver_remove_file(drv, &iunit_drvfs_attrs[i]);
|
}
|
|
int atomisp_drvfs_init(struct atomisp_device *isp)
|
{
|
struct device_driver *drv = isp->dev->driver;
|
int ret;
|
|
iunit_debug.isp = isp;
|
iunit_debug.drv = drv;
|
|
ret = iunit_drvfs_create_files(iunit_debug.drv);
|
if (ret) {
|
dev_err(isp->dev, "drvfs_create_files error: %d\n", ret);
|
iunit_drvfs_remove_files(iunit_debug.drv);
|
}
|
|
return ret;
|
}
|
|
void atomisp_drvfs_exit(void)
|
{
|
iunit_drvfs_remove_files(iunit_debug.drv);
|
}
|