123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- */
- #include <linux/completion.h>
- #include <linux/debugfs.h>
- #include <linux/dma-mapping.h>
- #include <linux/random.h>
- #include <linux/uaccess.h>
- #include <linux/msm_gsi.h>
- #include "gsi.h"
- #include "gsihal.h"
- #define GSI_MAX_MSG_LEN 4096
- #define TERR(fmt, args...) \
- pr_err("%s:%d " fmt, __func__, __LINE__, ## args)
- #define TDBG(fmt, args...) \
- pr_debug("%s:%d " fmt, __func__, __LINE__, ## args)
- #define PRT_STAT(fmt, args...) \
- pr_err(fmt, ## args)
- static struct dentry *dent;
- static char dbg_buff[GSI_MAX_MSG_LEN];
- static void *gsi_ipc_logbuf_low;
- static void gsi_wq_print_dp_stats(struct work_struct *work);
- static DECLARE_DELAYED_WORK(gsi_print_dp_stats_work, gsi_wq_print_dp_stats);
- static void gsi_wq_update_dp_stats(struct work_struct *work);
- static DECLARE_DELAYED_WORK(gsi_update_dp_stats_work, gsi_wq_update_dp_stats);
- static ssize_t gsi_dump_evt(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- u32 arg1;
- u32 arg2;
- unsigned long missing;
- char *sptr, *token;
- uint32_t val;
- struct gsi_evt_ctx *ctx;
- uint16_t i;
- if (count >= sizeof(dbg_buff))
- return -EINVAL;
- missing = copy_from_user(dbg_buff, buf, count);
- if (missing)
- return -EFAULT;
- dbg_buff[count] = '\0';
- sptr = dbg_buff;
- token = strsep(&sptr, " ");
- if (!token)
- return -EINVAL;
- if (kstrtou32(token, 0, &arg1))
- return -EINVAL;
- token = strsep(&sptr, " ");
- if (!token)
- return -EINVAL;
- if (kstrtou32(token, 0, &arg2))
- return -EINVAL;
- TDBG("arg1=%u arg2=%u\n", arg1, arg2);
- if (arg1 >= gsi_ctx->max_ev) {
- TERR("invalid evt ring id %u\n", arg1);
- return -EINVAL;
- }
- gsi_ctx->per.vote_clk_cb();
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_0,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX0 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_1,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX1 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_2,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX2 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_3,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX3 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_4,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX4 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_5,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX5 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_6,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX6 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_7,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX7 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_8,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX8 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_9,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX9 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_10,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX10 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_11,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX11 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_12,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX12 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_13,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d CTX13 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_SCRATCH_0,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d SCR0 0x%x\n", arg1, val);
- val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_SCRATCH_1,
- gsi_ctx->per.ee, arg1);
- TERR("EV%2d SCR1 0x%x\n", arg1, val);
- gsi_ctx->per.unvote_clk_cb();
- if (arg2) {
- ctx = &gsi_ctx->evtr[arg1];
- if (ctx->props.ring_base_vaddr) {
- for (i = 0; i < ctx->props.ring_len / 16; i++)
- TERR("EV%2d (0x%08llx) %08x %08x %08x %08x\n",
- arg1, ctx->props.ring_base_addr + i * 16,
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 0),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 4),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 8),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 12));
- } else {
- TERR("No VA supplied for event ring id %u\n", arg1);
- }
- }
- return count;
- }
- static ssize_t gsi_dump_ch(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- u32 arg1;
- u32 arg2;
- unsigned long missing;
- char *sptr, *token;
- struct gsi_chan_ctx *ctx;
- uint16_t i;
- if (count >= sizeof(dbg_buff))
- return -EINVAL;
- missing = copy_from_user(dbg_buff, buf, count);
- if (missing)
- return -EFAULT;
- dbg_buff[count] = '\0';
- sptr = dbg_buff;
- token = strsep(&sptr, " ");
- if (!token)
- return -EINVAL;
- if (kstrtou32(token, 0, &arg1))
- return -EINVAL;
- token = strsep(&sptr, " ");
- if (!token)
- return -EINVAL;
- if (kstrtou32(token, 0, &arg2))
- return -EINVAL;
- TDBG("arg1=%u arg2=%u\n", arg1, arg2);
- if (arg1 >= gsi_ctx->max_ch) {
- TERR("invalid chan id %u\n", arg1);
- return -EINVAL;
- }
- gsi_ctx->per.vote_clk_cb();
- gsi_dump_ch_info(arg1);
- gsi_ctx->per.unvote_clk_cb();
- if (arg2) {
- ctx = &gsi_ctx->chan[arg1];
- if (ctx->props.ring_base_vaddr) {
- for (i = 0; i < ctx->props.ring_len / 16; i++)
- TERR("CH%2d (0x%08llx) %08x %08x %08x %08x\n",
- arg1, ctx->props.ring_base_addr + i * 16,
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 0),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 4),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 8),
- *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
- i * 16 + 12));
- } else {
- TERR("No VA supplied for chan id %u\n", arg1);
- }
- }
- return count;
- }
- static void gsi_dump_ch_stats(struct gsi_chan_ctx *ctx)
- {
- if (!ctx->allocated)
- return;
- PRT_STAT("CH%2d:\n", ctx->props.ch_id);
- PRT_STAT("queued=%lu compl=%lu\n",
- ctx->stats.queued,
- ctx->stats.completed);
- PRT_STAT("cb->poll=%lu poll->cb=%lu poll_pend_irq=%lu\n",
- ctx->stats.callback_to_poll,
- ctx->stats.poll_to_callback,
- ctx->stats.poll_pending_irq);
- PRT_STAT("invalid_tre_error=%lu\n",
- ctx->stats.invalid_tre_error);
- PRT_STAT("poll_ok=%lu poll_empty=%lu\n",
- ctx->stats.poll_ok, ctx->stats.poll_empty);
- if (ctx->evtr)
- PRT_STAT("compl_evt=%lu\n",
- ctx->evtr->stats.completed);
- PRT_STAT("userdata_in_use=%lu\n", ctx->stats.userdata_in_use);
- PRT_STAT("ch_below_lo=%lu\n", ctx->stats.dp.ch_below_lo);
- PRT_STAT("ch_below_hi=%lu\n", ctx->stats.dp.ch_below_hi);
- PRT_STAT("ch_above_hi=%lu\n", ctx->stats.dp.ch_above_hi);
- PRT_STAT("time_empty=%lums\n", ctx->stats.dp.empty_time);
- PRT_STAT("\n");
- }
- static ssize_t gsi_dump_stats(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- int ch_id;
- int min, max, ret;
- ret = kstrtos32_from_user(buf, count, 0, &ch_id);
- if (ret)
- return ret;
- if (ch_id == -1) {
- min = 0;
- max = gsi_ctx->max_ch;
- } else if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
- !gsi_ctx->chan[ch_id].allocated) {
- goto error;
- } else {
- min = ch_id;
- max = ch_id + 1;
- }
- for (ch_id = min; ch_id < max; ch_id++)
- gsi_dump_ch_stats(&gsi_ctx->chan[ch_id]);
- return count;
- error:
- TERR("Usage: echo ch_id > stats. Use -1 for all\n");
- return -EINVAL;
- }
- static int gsi_dbg_create_stats_wq(void)
- {
- gsi_ctx->dp_stat_wq =
- create_singlethread_workqueue("gsi_stat");
- if (!gsi_ctx->dp_stat_wq) {
- TERR("failed create workqueue\n");
- return -ENOMEM;
- }
- return 0;
- }
- static void gsi_dbg_destroy_stats_wq(void)
- {
- cancel_delayed_work_sync(&gsi_update_dp_stats_work);
- cancel_delayed_work_sync(&gsi_print_dp_stats_work);
- flush_workqueue(gsi_ctx->dp_stat_wq);
- destroy_workqueue(gsi_ctx->dp_stat_wq);
- gsi_ctx->dp_stat_wq = NULL;
- }
- static ssize_t gsi_enable_dp_stats(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- int ch_id;
- bool enable;
- int ret;
- if (count >= sizeof(dbg_buff))
- goto error;
- if (copy_from_user(dbg_buff, buf, count))
- goto error;
- dbg_buff[count] = '\0';
- if (dbg_buff[0] != '+' && dbg_buff[0] != '-')
- goto error;
- enable = (dbg_buff[0] == '+');
- if (kstrtos32(dbg_buff + 1, 0, &ch_id))
- goto error;
- if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
- !gsi_ctx->chan[ch_id].allocated) {
- goto error;
- }
- if (gsi_ctx->chan[ch_id].enable_dp_stats == enable) {
- TERR("ch_%d: already enabled/disabled\n", ch_id);
- return -EINVAL;
- }
- gsi_ctx->chan[ch_id].enable_dp_stats = enable;
- if (enable)
- gsi_ctx->num_ch_dp_stats++;
- else
- gsi_ctx->num_ch_dp_stats--;
- if (enable) {
- if (gsi_ctx->num_ch_dp_stats == 1) {
- ret = gsi_dbg_create_stats_wq();
- if (ret)
- return ret;
- }
- cancel_delayed_work_sync(&gsi_update_dp_stats_work);
- queue_delayed_work(gsi_ctx->dp_stat_wq,
- &gsi_update_dp_stats_work, msecs_to_jiffies(10));
- } else if (!enable && gsi_ctx->num_ch_dp_stats == 0) {
- gsi_dbg_destroy_stats_wq();
- }
- return count;
- error:
- TERR("Usage: echo [+-]ch_id > enable_dp_stats\n");
- return -EINVAL;
- }
- static ssize_t gsi_set_max_elem_dp_stats(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- u32 ch_id;
- u32 max_elem;
- unsigned long missing;
- char *sptr, *token;
- if (count >= sizeof(dbg_buff))
- goto error;
- missing = copy_from_user(dbg_buff, buf, count);
- if (missing)
- goto error;
- dbg_buff[count] = '\0';
- sptr = dbg_buff;
- token = strsep(&sptr, " ");
- if (!token) {
- TERR("\n");
- goto error;
- }
- if (kstrtou32(token, 0, &ch_id)) {
- TERR("\n");
- goto error;
- }
- token = strsep(&sptr, " ");
- if (!token) {
- /* get */
- if (kstrtou32(dbg_buff, 0, &ch_id))
- goto error;
- if (ch_id >= gsi_ctx->max_ch)
- goto error;
- PRT_STAT("ch %d: max_re_expected=%d\n", ch_id,
- gsi_ctx->chan[ch_id].props.max_re_expected);
- return count;
- }
- if (kstrtou32(token, 0, &max_elem)) {
- TERR("\n");
- goto error;
- }
- TDBG("ch_id=%u max_elem=%u\n", ch_id, max_elem);
- if (ch_id >= gsi_ctx->max_ch) {
- TERR("invalid chan id %u\n", ch_id);
- goto error;
- }
- gsi_ctx->chan[ch_id].props.max_re_expected = max_elem;
- return count;
- error:
- TERR("Usage: (set) echo <ch_id> <max_elem> > max_elem_dp_stats\n");
- TERR("Usage: (get) echo <ch_id> > max_elem_dp_stats\n");
- return -EINVAL;
- }
- static void gsi_wq_print_dp_stats(struct work_struct *work)
- {
- int ch_id;
- for (ch_id = 0; ch_id < gsi_ctx->max_ch; ch_id++) {
- if (gsi_ctx->chan[ch_id].print_dp_stats)
- gsi_dump_ch_stats(&gsi_ctx->chan[ch_id]);
- }
- queue_delayed_work(gsi_ctx->dp_stat_wq, &gsi_print_dp_stats_work,
- msecs_to_jiffies(1000));
- }
- static void gsi_dbg_update_ch_dp_stats(struct gsi_chan_ctx *ctx)
- {
- uint16_t start_hw;
- uint16_t end_hw;
- uint64_t rp_hw;
- uint64_t wp_hw;
- int ee = gsi_ctx->per.ee;
- uint16_t used_hw;
- gsi_ctx->per.vote_clk_cb();
- rp_hw = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_4,
- ee, ctx->props.ch_id);
- rp_hw |= ((uint64_t)gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_5,
- ee, ctx->props.ch_id)) << 32;
- wp_hw = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_6,
- ee, ctx->props.ch_id);
- wp_hw |= ((uint64_t)gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_7,
- ee, ctx->props.ch_id)) << 32;
- gsi_ctx->per.unvote_clk_cb();
- start_hw = gsi_find_idx_from_addr(&ctx->ring, rp_hw);
- end_hw = gsi_find_idx_from_addr(&ctx->ring, wp_hw);
- if (end_hw >= start_hw)
- used_hw = end_hw - start_hw;
- else
- used_hw = ctx->ring.max_num_elem + 1 - (start_hw - end_hw);
- TDBG("ch %d used %d\n", ctx->props.ch_id, used_hw);
- gsi_update_ch_dp_stats(ctx, used_hw);
- }
- static void gsi_wq_update_dp_stats(struct work_struct *work)
- {
- int ch_id;
- for (ch_id = 0; ch_id < gsi_ctx->max_ch; ch_id++) {
- if (gsi_ctx->chan[ch_id].allocated &&
- gsi_ctx->chan[ch_id].enable_dp_stats)
- gsi_dbg_update_ch_dp_stats(&gsi_ctx->chan[ch_id]);
- }
- queue_delayed_work(gsi_ctx->dp_stat_wq, &gsi_update_dp_stats_work,
- msecs_to_jiffies(10));
- }
- static ssize_t gsi_rst_stats(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- int ch_id;
- int min, max, ret;
- ret = kstrtos32_from_user(buf, count, 0, &ch_id);
- if (ret)
- return ret;
- if (ch_id == -1) {
- min = 0;
- max = gsi_ctx->max_ch;
- } else if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
- !gsi_ctx->chan[ch_id].allocated) {
- goto error;
- } else {
- min = ch_id;
- max = ch_id + 1;
- }
- for (ch_id = min; ch_id < max; ch_id++)
- memset(&gsi_ctx->chan[ch_id].stats, 0,
- sizeof(gsi_ctx->chan[ch_id].stats));
- return count;
- error:
- TERR("Usage: echo ch_id > rst_stats. Use -1 for all\n");
- return -EINVAL;
- }
- static ssize_t gsi_print_dp_stats(struct file *file,
- const char __user *buf, size_t count, loff_t *ppos)
- {
- int ch_id;
- bool enable;
- int ret;
- if (count >= sizeof(dbg_buff))
- goto error;
- if (copy_from_user(dbg_buff, buf, count))
- goto error;
- dbg_buff[count] = '\0';
- if (dbg_buff[0] != '+' && dbg_buff[0] != '-')
- goto error;
- enable = (dbg_buff[0] == '+');
- if (kstrtos32(dbg_buff + 1, 0, &ch_id))
- goto error;
- if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
- !gsi_ctx->chan[ch_id].allocated) {
- goto error;
- }
- if (gsi_ctx->chan[ch_id].print_dp_stats == enable) {
- TERR("ch_%d: already enabled/disabled\n", ch_id);
- return -EINVAL;
- }
- gsi_ctx->chan[ch_id].print_dp_stats = enable;
- if (enable)
- gsi_ctx->num_ch_dp_stats++;
- else
- gsi_ctx->num_ch_dp_stats--;
- if (enable) {
- if (gsi_ctx->num_ch_dp_stats == 1) {
- ret = gsi_dbg_create_stats_wq();
- if (ret)
- return ret;
- }
- cancel_delayed_work_sync(&gsi_print_dp_stats_work);
- queue_delayed_work(gsi_ctx->dp_stat_wq,
- &gsi_print_dp_stats_work, msecs_to_jiffies(10));
- } else if (!enable && gsi_ctx->num_ch_dp_stats == 0) {
- gsi_dbg_destroy_stats_wq();
- }
- return count;
- error:
- TERR("Usage: echo [+-]ch_id > print_dp_stats\n");
- return -EINVAL;
- }
- static ssize_t gsi_enable_ipc_low(struct file *file,
- const char __user *ubuf, size_t count, loff_t *ppos)
- {
- s8 option = 0;
- int ret;
- ret = kstrtos8_from_user(ubuf, count, 0, &option);
- if (ret)
- return ret;
- mutex_lock(&gsi_ctx->mlock);
- if (option) {
- if (!gsi_ipc_logbuf_low) {
- gsi_ipc_logbuf_low =
- ipc_log_context_create(GSI_IPC_LOG_PAGES,
- "gsi_low", MINIDUMP_MASK);
- if (gsi_ipc_logbuf_low == NULL)
- TERR("failed to get ipc_logbuf_low\n");
- }
- gsi_ctx->ipc_logbuf_low = gsi_ipc_logbuf_low;
- } else {
- gsi_ctx->ipc_logbuf_low = NULL;
- }
- mutex_unlock(&gsi_ctx->mlock);
- return count;
- }
- static ssize_t gsi_read_gsi_hw_profiling_stats(struct file *file,
- char __user *buf, size_t count, loff_t *ppos)
- {
- struct gsi_hw_profiling_data stats;
- int ret, nbytes, cnt = 0;
- u64 totalCycles = 0, util = 0;
- if (gsi_ctx->per.ver < GSI_VER_2_9) {
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "This feature only support on GSI2.9+\n");
- cnt += nbytes;
- goto done;
- }
- gsi_ctx->per.vote_clk_cb();
- ret = gsi_get_hw_profiling_stats(&stats);
- gsi_ctx->per.unvote_clk_cb();
- if (!ret) {
- totalCycles = stats.mcs_busy_cnt + stats.mcs_idle_cnt +
- stats.bp_and_pending_cnt;
- if (totalCycles != 0)
- util = div_u64(
- 100 * (stats.mcs_busy_cnt + stats.bp_and_pending_cnt),
- totalCycles);
- else
- util = 0;
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "bp_count=0x%llx\n"
- "bp_and_pending_count=0x%llx\n"
- "mcs_busy=0x%llx\n"
- "mcs_idle=0x%llx\n"
- "total_cycle_count=0x%llx\n"
- "utilization_percentage=%llu%%\n",
- stats.bp_cnt,
- stats.bp_and_pending_cnt,
- stats.mcs_busy_cnt,
- stats.mcs_idle_cnt,
- totalCycles,
- util);
- cnt += nbytes;
- } else {
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "Fail to read GSI HW Profiling stats\n");
- cnt += nbytes;
- }
- done:
- return simple_read_from_buffer(buf, count, ppos, dbg_buff, cnt);
- }
- static ssize_t gsi_read_gsi_fw_version(struct file *file,
- char __user *buf, size_t count, loff_t *ppos)
- {
- struct gsi_fw_version ver;
- int ret, nbytes, cnt = 0;
- if (gsi_ctx->per.ver < GSI_VER_2_9) {
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "This feature only support on GSI2.9+\n");
- cnt += nbytes;
- goto done;
- }
- gsi_ctx->per.vote_clk_cb();
- ret = gsi_get_fw_version(&ver);
- gsi_ctx->per.unvote_clk_cb();
- if (!ret) {
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "hw=%d\nflavor=%d\nfw=%d\n",
- ver.hw,
- ver.flavor,
- ver.fw);
- cnt += nbytes;
- } else {
- nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
- "Fail to read GSI FW version\n");
- cnt += nbytes;
- }
- done:
- return simple_read_from_buffer(buf, count, ppos, dbg_buff, cnt);
- }
- static const struct file_operations gsi_ev_dump_ops = {
- .write = gsi_dump_evt,
- };
- static const struct file_operations gsi_ch_dump_ops = {
- .write = gsi_dump_ch,
- };
- static const struct file_operations gsi_stats_ops = {
- .write = gsi_dump_stats,
- };
- static const struct file_operations gsi_enable_dp_stats_ops = {
- .write = gsi_enable_dp_stats,
- };
- static const struct file_operations gsi_max_elem_dp_stats_ops = {
- .write = gsi_set_max_elem_dp_stats,
- };
- static const struct file_operations gsi_rst_stats_ops = {
- .write = gsi_rst_stats,
- };
- static const struct file_operations gsi_print_dp_stats_ops = {
- .write = gsi_print_dp_stats,
- };
- static const struct file_operations gsi_ipc_low_ops = {
- .write = gsi_enable_ipc_low,
- };
- static const struct file_operations gsi_hw_profiling_ops = {
- .read = gsi_read_gsi_hw_profiling_stats,
- };
- static const struct file_operations gsi_ver_ops = {
- .read = gsi_read_gsi_fw_version,
- };
- void gsi_debugfs_init(void)
- {
- static struct dentry *dfile;
- const mode_t write_only_mode = 0220;
- const mode_t read_only_mode = 0440;
- dent = debugfs_create_dir("gsi", 0);
- if (IS_ERR(dent)) {
- TERR("fail to create dir\n");
- return;
- }
- dfile = debugfs_create_file("ev_dump", write_only_mode,
- dent, 0, &gsi_ev_dump_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create ev_dump file\n");
- goto fail;
- }
- dfile = debugfs_create_file("ch_dump", write_only_mode,
- dent, 0, &gsi_ch_dump_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create ch_dump file\n");
- goto fail;
- }
- dfile = debugfs_create_file("stats", write_only_mode, dent,
- 0, &gsi_stats_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create stats file\n");
- goto fail;
- }
- dfile = debugfs_create_file("enable_dp_stats", write_only_mode, dent,
- 0, &gsi_enable_dp_stats_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create stats file\n");
- goto fail;
- }
- dfile = debugfs_create_file("max_elem_dp_stats", write_only_mode,
- dent, 0, &gsi_max_elem_dp_stats_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create stats file\n");
- goto fail;
- }
- dfile = debugfs_create_file("rst_stats", write_only_mode,
- dent, 0, &gsi_rst_stats_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create stats file\n");
- goto fail;
- }
- dfile = debugfs_create_file("print_dp_stats",
- write_only_mode, dent, 0, &gsi_print_dp_stats_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("fail to create stats file\n");
- goto fail;
- }
- dfile = debugfs_create_file("ipc_low", write_only_mode,
- dent, 0, &gsi_ipc_low_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("could not create ipc_low\n");
- goto fail;
- }
- dfile = debugfs_create_file("gsi_hw_profiling_stats", read_only_mode,
- dent, 0, &gsi_hw_profiling_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("could not create gsi_hw_profiling_stats\n");
- goto fail;
- }
- dfile = debugfs_create_file("gsi_fw_version", read_only_mode, dent, 0,
- &gsi_ver_ops);
- if (!dfile || IS_ERR(dfile)) {
- TERR("could not create gsi_fw_version\n");
- goto fail;
- }
- return;
- fail:
- debugfs_remove_recursive(dent);
- }
|