Merge tag 'KERNEL.PLATFORM.1.0.r1-18400-kernel.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.10 into android13-5.10-waipio

"KERNEL.PLATFORM.1.0.r1-18400-kernel.0"

* tag 'KERNEL.PLATFORM.1.0.r1-18400-kernel.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.10:
  drivers: dcvs: llcc_miss: Remove Secure Device Check
  defconfig: Enable PM8008 module for neo LE
  arm64: config: Enable LLCC Miss and BUS Profile
  drivers: dcvs: llcc_miss: Add llcc miss stats driver
  interconnect: qcom: icc-rpmh: enable support for no secondary display
  clk: qcom: gcc-anorak: Add CLK_DONT_HOLD_STATE to usb2_clkref
  soc: qcom: smcinvoke: Add dependent modules for smcinvoke
  drivers: scm: Change order of dload legacy support check
  i2c: i2c-master-msm-geni: add null pointer check in event call back
  drivers: qseecom: Define .compat_ioctl based on CONFIG_COMPAT
  build.config: Move smcinvoke and qseecom to early init
  msm: kgsl: Fix gpu work period update for legacy path
  Merge remote-tracking branch into HEAD
  UPSTREAM: af_unix: Fix garbage collector racing against connect()
  ANDROID: irq: put irq_resolve_mapping under protection of __irq_enter_raw
  UPSTREAM: af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
  ANDROID: ABI fixup for abi break in struct dst_ops
  BACKPORT: net: fix __dst_negative_advice() race
  power: reset: Disable support of dynamic download mode (ramdump)

 Conflicts:
	android/abi_gki_aarch64.xml

Change-Id: Ibf2399d85835c5e2e28569a4df8c5fd4e7b3fb72
This commit is contained in:
Michael Bestas 2024-12-16 00:40:29 +02:00
commit bcf90117d7
No known key found for this signature in database
GPG Key ID: CC95044519BE6669
23 changed files with 684 additions and 24 deletions

View File

@ -1,2 +1,2 @@
c02e95e82b343fe03d03dfd6fb74ecc2077e1ee3
android12-5.10-2024-05_r1
7e657aa362f21c8fb472e03a22795b18f831a178
android12-5.10-2024-08_r1

View File

@ -78522,9 +78522,9 @@
<pointer-type-def type-id='512ac7cc' size-in-bits='64' id='ac58af12'/>
<pointer-type-def type-id='b254b8db' size-in-bits='64' id='ac5f2363'/>
<pointer-type-def type-id='49a0ad34' size-in-bits='64' id='ac6963b2'/>
<class-decl name='prot_inuse' size-in-bits='2048' is-struct='yes' visibility='default' filepath='net/core/sock.c' line='3371' column='1' id='ac763c5d'>
<class-decl name='prot_inuse' size-in-bits='2048' is-struct='yes' visibility='default' filepath='net/core/sock.c' line='3369' column='1' id='ac763c5d'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='val' type-id='93e41790' visibility='default' filepath='net/core/sock.c' line='3372' column='1'/>
<var-decl name='val' type-id='93e41790' visibility='default' filepath='net/core/sock.c' line='3370' column='1'/>
</data-member>
</class-decl>
<function-type size-in-bits='64' id='ac765b39'>

View File

@ -214,6 +214,7 @@ CONFIG_PWM_QTI_LPG=m
CONFIG_QCOM_AOSS_QMP=m
CONFIG_QCOM_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_QCOM_BAM_DMA=m
CONFIG_QCOM_BUS_PROF=m
CONFIG_QCOM_BWMON=m
CONFIG_QCOM_BWPROF=m
# CONFIG_QCOM_CLK_APCC_MSM8996 is not set
@ -249,6 +250,7 @@ CONFIG_QCOM_KGSL_CONTEXT_DEBUG=y
CONFIG_QCOM_KGSL_IOCOHERENCY_DEFAULT=y
CONFIG_QCOM_LAZY_MAPPING=m
CONFIG_QCOM_LLCC=m
CONFIG_QCOM_LLCC_MISS=m
CONFIG_QCOM_LLCC_PERFMON=m
CONFIG_QCOM_LLCC_PMU=m
CONFIG_QCOM_LOGBUF_VENDOR_HOOKS=m

View File

@ -369,6 +369,7 @@ CONFIG_REGMAP_QTI_DEBUGFS=m
CONFIG_REGMAP_SPMI=m
CONFIG_REGULATOR_DEBUG_CONTROL=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_QCOM_PM8008=m
CONFIG_REGULATOR_QCOM_RPMH=m
CONFIG_REGULATOR_QTI_FIXED_VOLTAGE=y
CONFIG_REGULATOR_RPMH=m

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, 2023, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk-provider.h>
@ -3773,6 +3773,7 @@ static struct clk_branch gcc_usb2_0_clkref_en = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb2_0_clkref_en",
.flags = CLK_DONT_HOLD_STATE,
.ops = &clk_branch2_ops,
},
},

View File

@ -528,18 +528,15 @@ int __qcom_scm_set_dload_mode(struct device *dev, enum qcom_download_mode mode)
void qcom_scm_set_download_mode(enum qcom_download_mode mode,
phys_addr_t tcsr_boot_misc)
{
bool avail;
int ret = 0;
struct device *dev = __scm ? __scm->dev : NULL;
avail = __qcom_scm_is_call_available(dev,
QCOM_SCM_SVC_BOOT,
QCOM_SCM_BOOT_SET_DLOAD_MODE);
if (avail) {
if (tcsr_boot_misc || (__scm && __scm->dload_mode_addr)) {
ret = qcom_scm_io_writel(tcsr_boot_misc ? : __scm->dload_mode_addr, mode);
} else if (__qcom_scm_is_call_available(dev,
QCOM_SCM_SVC_BOOT,
QCOM_SCM_BOOT_SET_DLOAD_MODE)) {
ret = __qcom_scm_set_dload_mode(dev, mode);
} else if (tcsr_boot_misc || (__scm && __scm->dload_mode_addr)) {
ret = qcom_scm_io_writel(
tcsr_boot_misc ? : __scm->dload_mode_addr, mode);
} else {
dev_err(dev,
"No available mechanism for setting download mode\n");
@ -806,6 +803,34 @@ int qcom_scm_get_sec_dump_state(u32 *dump_state)
}
EXPORT_SYMBOL(qcom_scm_get_sec_dump_state);
int __qcom_scm_get_llcc_missrate(struct device *dev, phys_addr_t in_buf,
size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size)
{
int ret;
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_MISSRATE,
.cmd = QCOM_SCM_GET_LLCC_MISSRATE_STATS_ID,
.owner = ARM_SMCCC_OWNER_SIP,
.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL),
};
desc.args[0] = in_buf;
desc.args[1] = in_buf_size;
desc.args[2] = out_buf;
desc.args[3] = out_buf_size;
ret = qcom_scm_call(dev, &desc, NULL);
return ret;
}
int qcom_scm_get_llcc_missrate(phys_addr_t in_buf,
size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size)
{
return __qcom_scm_get_llcc_missrate(__scm ? __scm->dev : NULL, in_buf,
in_buf_size, out_buf, out_buf_size);
}
EXPORT_SYMBOL_GPL(qcom_scm_get_llcc_missrate);
int qcom_scm_assign_dump_table_region(bool is_assign, phys_addr_t addr, size_t size)
{
struct qcom_scm_desc desc = {

View File

@ -231,6 +231,9 @@ int qcom_scm_handle_wait(struct device *dev, int scm_ret,
#define QCOM_SCM_LMH_LIMIT_PROFILE_CHANGE 0x01
#define QCOM_SCM_LMH_LIMIT_DCVSH 0x10
#define QCOM_SCM_GET_LLCC_MISSRATE_STATS_ID 0x14
#define QCOM_SCM_SVC_MISSRATE 0x06
extern void __qcom_scm_init(void);
/* common error codes */

View File

@ -146,11 +146,6 @@ static void log_profiling_info(struct adreno_device *adreno_dev, u32 *rcvd)
if (context == NULL)
return;
/* protected GPU work must not be reported */
if (!(context->flags & KGSL_CONTEXT_SECURE))
kgsl_work_period_update(device, context->proc_priv->period,
cmd->active);
info.timestamp = cmd->ts;
info.rb_id = adreno_get_level(context);
info.gmu_dispatch_queue = context->gmu_dispatch_queue;
@ -163,6 +158,10 @@ static void log_profiling_info(struct adreno_device *adreno_dev, u32 *rcvd)
info.active = cmd->active;
info.retired_on_gmu = cmd->retired_on_gmu;
/* protected GPU work must not be reported */
if (!(context->flags & KGSL_CONTEXT_SECURE))
kgsl_work_period_update(device, context->proc_priv->period, info.active);
trace_adreno_cmdbatch_retired(context, &info, 0, 0, 0);
log_kgsl_cmdbatch_retired_event(context->id, cmd->ts, context->priority,

View File

@ -799,8 +799,16 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev)
static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str,
void *ptr)
{
struct geni_i2c_dev *gi2c = ptr;
u32 m_stat = cb_str->status;
struct geni_i2c_dev *gi2c;
u32 m_stat;
if (!ptr || !cb_str) {
pr_err("%s: Invalid ev_cb buffer\n", __func__);
return;
}
gi2c = (struct geni_i2c_dev *)ptr;
m_stat = cb_str->status;
switch (cb_str->cb_event) {
case MSM_GPI_QUP_ERROR:

View File

@ -324,8 +324,8 @@ static struct regmap *qcom_icc_rpmh_map(struct platform_device *pdev,
static bool is_voter_disabled(char *voter)
{
if ((strnstr(voter, "disp", strlen(voter)) &&
(socinfo_get_part_info(PART_DISPLAY) || socinfo_get_part_info(PART_DISPLAY1))) ||
if ((!strcmp(voter, "disp") && socinfo_get_part_info(PART_DISPLAY)) ||
(!strcmp(voter, "disp2") && socinfo_get_part_info(PART_DISPLAY1)) ||
(strnstr(voter, "cam", strlen(voter)) && socinfo_get_part_info(PART_CAMERA)))
return true;
@ -359,7 +359,12 @@ static int qcom_icc_init_disabled_parts(struct qcom_icc_provider *qp)
if (!qn)
continue;
if (strnstr(qn->name, voter_name, strlen(qn->name)))
/*
* Find the ICC node to be disabled by comparing voter_name in
* node name string, adjust the start position accordingly
*/
if (!strcmp(qn->name + (strlen(qn->name) - strlen(voter_name)),
voter_name))
qn->disabled = true;
}
}

View File

@ -8509,7 +8509,9 @@ static int qseecom_release(struct inode *inode, struct file *file)
static const struct file_operations qseecom_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = qseecom_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_qseecom_ioctl,
#endif
.open = qseecom_open,
.release = qseecom_release
};

View File

@ -98,7 +98,9 @@ static int param_set_download_mode(const char *val,
if (ret)
return ret;
msm_enable_dump_mode(true);
msm_enable_dump_mode(enable_dump);
if (!enable_dump)
qcom_scm_disable_sdi();
return 0;
}

View File

@ -1171,6 +1171,7 @@ config QCOM_HUNG_TASK_ENH
config QCOM_SMCINVOKE
tristate "Secure QSEE Support"
depends on QCOM_SCM && QCOM_MEM_BUF
help
Enable SMCInvoke driver which supports capability based secure
communication between QTI Secure Execution Environment (QSEE)

View File

@ -76,6 +76,29 @@ config QTI_HW_MEMLAT_SCMI_CLIENT
driver, and interface driver will use this handle to communicate with
memlat HW.
config QCOM_LLCC_MISS
tristate "Qualcomm Technologies Inc. LLCC_MISS_STATS Driver"
depends on ARCH_QCOM && QCOM_BUS_PROF
default n
help
This enables the QCOM LLCC miss stats driver which exposes LLCC miss
stats to user space clients at modest time intervals for the intention
of profiling.
The purpose of the driver is to enable the monitoring of LLCC misses
at regular intervals and providing the miss rate data to the user
space clients upon read.
config QCOM_BUS_PROF
tristate "Qualcomm Technologies Inc. BUS_PROF Driver"
depends on ARCH_QCOM
default n
help
This enables the QCOM bus profiling common framework and ftraces,
which provide support for a variety of features. These features
include memory latency, LLCC miss, and LLCC occupancy, all of
which are supported on certain Qualcomm Technologies, Inc.
(QTI) chipsets.
config QTI_PMU_SCMI_CLIENT
tristate "Qualcomm Technologies Inc. SCMI client driver for PMU"

View File

@ -7,6 +7,8 @@ qcom-dcvs-y := dcvs.o dcvs_icc.o dcvs_epss.o trace-dcvs.o
obj-$(CONFIG_QCOM_MEMLAT) += memlat.o
obj-$(CONFIG_QCOM_BWMON) += bwmon.o
obj-$(CONFIG_QCOM_BWPROF) += bwprof.o
obj-$(CONFIG_QCOM_BUS_PROF) += trace-bus-prof.o
obj-$(CONFIG_QCOM_LLCC_MISS) += llcc_miss.o
obj-$(CONFIG_QTI_PMU_SCMI_CLIENT) += pmu_scmi.o
obj-$(CONFIG_QTI_C1DCVS_SCMI_CLIENT) += c1dcvs_scmi.o
obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/types.h>
#ifndef _QCOM_BUS_PROF_H
#define _QCOM_BUS_PROF_H
#define MAX_CONCURRENT_MASTERS 2
struct llcc_miss_buf {
u8 master_id;
uint16_t miss_info;
u32 rd_miss;
u32 wr_miss;
u32 all_access;
} __packed;
#endif /* _QCOM_BUS_PROF_H */

View File

@ -0,0 +1,497 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/debugfs.h>
#include <linux/hrtimer.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/qcom_scm.h>
#include <linux/qtee_shmbridge.h>
#include <linux/slab.h>
#include "bus_prof.h"
#include "trace-bus-prof.h"
#define SAMPLE_MS 10
#define DDR_OUT_BUF_MAGIC (0xDD4)
enum cmd {
LLCC_MISS_START_PROFILING = 1,
LLCC_MISS_GET_DATA = 2,
LLCC_MISS_STOP_PROFILING = 3,
};
enum error {
E_SUCCESS = 0, /* Operation successful */
E_FAILURE = 1, /* Operation failed due to unknown err*/
E_NULL_PARAM = 2,/* Null Parameter */
E_INVALID_ARG = 3,/* Arg is not recognized */
E_BAD_ADDRESS = 4,/* Ptr arg is bad address */
E_INVALID_ARG_LEN = 5,/* Arg length is wrong */
E_NOT_SUPPORTED = 6,/* Operation not supported */
E_UNINITIALIZED = 7,/* Operation not permitted on platform */
E_PARTIAL_DUMP = 8,/* Operation not permitted right now */
E_RESERVED = 0x7FFFFFFF
};
enum llcc_miss_masters {
CPU = 0,
GPU,
NSP,
MAX_MASTER,
};
static char *master_names[MAX_MASTER] = {"CPU", "GPU", "NSP"};
struct llcc_miss_start_req {
u32 cmd_id;
u32 active_masters;
} __packed;
struct llcc_miss_resp {
u32 cmd_id;
enum error status;
} __packed;
struct llcc_miss_get_req {
u32 cmd_id;
u8 *buf_ptr;
u32 buf_size;
u32 type; /* Stop : 0, Reset : 1 */
} __packed;
struct llcc_miss_stop_req {
u32 cmd_id;
} __packed;
/* cmd_id is expected to be defined first for each member of the union */
union llcc_miss_req {
struct llcc_miss_start_req start_req;
struct llcc_miss_get_req get_req;
struct llcc_miss_stop_req stop_req;
} __packed;
struct llcc_cmd_buf {
union llcc_miss_req llcc_miss_req;
struct llcc_miss_resp llcc_miss_resp;
u32 req_size;
} __packed;
struct llcc_miss_data {
struct llcc_miss_buf master_buf[MAX_CONCURRENT_MASTERS];
enum error err;
u16 magic;
u64 qtime;
} __packed;
struct miss_sample {
u64 ts;
u16 measured_miss_rate;
} __packed;
struct llcc_miss_dev_data {
struct work_struct work;
struct workqueue_struct *wq;
struct hrtimer hrtimer;
u16 max_samples;
u16 size_of_line;
u32 active_masters;
u32 available_masters;
struct llcc_miss_data *data;
struct mutex lock;
};
struct master_data {
u16 curr_idx;
u16 unread_samples;
struct miss_sample *miss_data;
char buf[PAGE_SIZE];
};
static struct master_data mdata[MAX_MASTER];
static struct dentry *llcc_miss_dir;
static struct llcc_miss_dev_data *llcc_miss;
static ssize_t get_last_samples(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
int index = 0, ret = 0, m_idx;
int i = 0, size = 0, enable;
char *master_name;
mutex_lock(&llcc_miss->lock);
if (!llcc_miss->active_masters) {
pr_err("No master is enabled for mem miss\n");
goto unlock;
}
master_name = file->private_data;
for (m_idx = 0; m_idx < MAX_MASTER ; m_idx++) {
if (!strcasecmp(master_names[m_idx], master_name))
break;
}
enable = (llcc_miss->active_masters & BIT(m_idx));
if (!enable) {
pr_err("%s memory miss is not enabled\n", master_names[m_idx]);
ret = -EINVAL;
goto unlock;
}
index = (mdata[m_idx].curr_idx - mdata[m_idx].unread_samples +
llcc_miss->max_samples) % llcc_miss->max_samples;
for (i = 0; i < mdata[m_idx].unread_samples; i++) {
size += scnprintf(mdata[m_idx].buf + size, PAGE_SIZE - size,
"%llx\t%x\n", mdata[m_idx].miss_data[index].ts,
mdata[m_idx].miss_data[index].measured_miss_rate);
index = (index + 1) % llcc_miss->max_samples;
}
mdata[m_idx].unread_samples = 0;
ret = simple_read_from_buffer(user_buf, count, ppos, mdata[m_idx].buf, size);
unlock:
mutex_unlock(&llcc_miss->lock);
return ret;
}
static int send_llcc_miss_profiling_command(const void *req)
{
int ret = 0;
u32 qseos_cmd_id = 0;
struct llcc_miss_resp *rsp = NULL;
size_t req_size = 0, rsp_size = 0;
struct qtee_shm shm = {0};
if (!req)
return -EINVAL;
rsp = &((struct llcc_cmd_buf *)req)->llcc_miss_resp;
rsp_size = sizeof(struct llcc_miss_resp);
req_size = ((struct llcc_cmd_buf *)req)->req_size;
qseos_cmd_id = *(u32 *)req;
ret = qtee_shmbridge_allocate_shm(PAGE_ALIGN(req_size + rsp_size), &shm);
if (ret) {
pr_err("qtee_shmbridge_allocate_shm failed, ret :%d\n", ret);
return -ENOMEM;
}
memcpy(shm.vaddr, req, req_size);
qtee_shmbridge_flush_shm_buf(&shm);
switch (qseos_cmd_id) {
case LLCC_MISS_START_PROFILING:
case LLCC_MISS_GET_DATA:
case LLCC_MISS_STOP_PROFILING:
/* Send the command to TZ */
ret = qcom_scm_get_llcc_missrate(shm.paddr, req_size,
shm.paddr + req_size, rsp_size);
break;
default:
pr_err("cmd_id %d is not supported.\n",
qseos_cmd_id);
ret = -EINVAL;
}
qtee_shmbridge_inv_shm_buf(&shm);
memcpy(rsp, (char *)shm.vaddr + req_size, rsp_size);
qtee_shmbridge_free_shm(&shm);
/* Verify cmd id and Check that request succeeded. */
if (rsp->status != 0 ||
qseos_cmd_id != rsp->cmd_id) {
ret = -1;
pr_err("Status: %d,Cmd: %d\n",
rsp->status,
rsp->cmd_id);
}
return ret;
}
static int start_memory_miss_stats(void)
{
int ret = 0;
struct llcc_cmd_buf *llcc_cmd_buf = NULL;
llcc_cmd_buf = kzalloc(sizeof(*llcc_cmd_buf), GFP_KERNEL);
if (!llcc_cmd_buf)
return -ENOMEM;
llcc_cmd_buf->llcc_miss_req.start_req.cmd_id = LLCC_MISS_START_PROFILING;
llcc_cmd_buf->llcc_miss_req.start_req.active_masters = llcc_miss->active_masters;
llcc_cmd_buf->req_size = sizeof(struct llcc_miss_start_req);
ret = send_llcc_miss_profiling_command(llcc_cmd_buf);
if (ret) {
pr_err("Error in %s, ret = %d\n", __func__, ret);
goto out;
}
if (!hrtimer_active(&llcc_miss->hrtimer))
hrtimer_start(&llcc_miss->hrtimer,
ms_to_ktime(SAMPLE_MS), HRTIMER_MODE_REL_PINNED);
out:
kfree(llcc_cmd_buf);
return ret;
}
static int stop_memory_miss_stats(void)
{
int ret;
struct llcc_cmd_buf *llcc_cmd_buf = NULL;
hrtimer_cancel(&llcc_miss->hrtimer);
cancel_work_sync(&llcc_miss->work);
llcc_cmd_buf = kzalloc(sizeof(*llcc_cmd_buf), GFP_KERNEL);
if (!llcc_cmd_buf)
return -ENOMEM;
llcc_cmd_buf->llcc_miss_req.stop_req.cmd_id = LLCC_MISS_STOP_PROFILING;
llcc_cmd_buf->req_size = sizeof(struct llcc_miss_stop_req);
ret = send_llcc_miss_profiling_command(llcc_cmd_buf);
if (ret)
pr_err("Error in %s, ret = %d\n", __func__, ret);
kfree(llcc_cmd_buf);
return 0;
}
static int set_mon_enabled(void *data, u64 val)
{
char *master_name = data;
int i, ret = 0;
u32 count, enable = val ? 1 : 0;
mutex_lock(&llcc_miss->lock);
for (i = 0; i < MAX_MASTER; i++) {
if (!strcasecmp(master_names[i], master_name))
break;
}
if (enable == (llcc_miss->active_masters & BIT(i)))
goto unlock;
count = hweight32(llcc_miss->active_masters);
if (count >= MAX_CONCURRENT_MASTERS && enable) {
pr_err("Max masters already enabled\n");
ret = -EINVAL;
goto unlock;
}
mutex_unlock(&llcc_miss->lock);
if (count)
stop_memory_miss_stats();
mutex_lock(&llcc_miss->lock);
llcc_miss->active_masters = (llcc_miss->active_masters ^ BIT(i));
if (llcc_miss->active_masters)
start_memory_miss_stats();
unlock:
mutex_unlock(&llcc_miss->lock);
return ret;
}
static int get_mon_enabled(void *data, u64 *val)
{
char *master_name = data;
int i;
mutex_lock(&llcc_miss->lock);
for (i = 0; i < MAX_MASTER; i++) {
if (!strcasecmp(master_names[i], master_name))
break;
}
if (llcc_miss->active_masters & BIT(i))
*val = 1;
else
*val = 0;
mutex_unlock(&llcc_miss->lock);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(set_mon_enabled_ops, get_mon_enabled, set_mon_enabled, "%llu\n");
static const struct file_operations show_last_samples_ops = {
.read = get_last_samples,
.open = simple_open,
.llseek = default_llseek,
};
static void llcc_miss_update_work(struct work_struct *work)
{
int ret = 0, i, m;
u16 magic;
struct llcc_cmd_buf *llcc_cmd_buf;
struct qtee_shm buf_shm = {0};
const int bufsize = sizeof(struct llcc_miss_data);
llcc_cmd_buf = kzalloc(sizeof(*llcc_cmd_buf), GFP_KERNEL);
if (!llcc_cmd_buf)
return;
ret = qtee_shmbridge_allocate_shm(PAGE_ALIGN(bufsize), &buf_shm);
if (ret) {
pr_err("shmbridge alloc buf failed\n");
return;
}
llcc_cmd_buf->llcc_miss_req.get_req.cmd_id = LLCC_MISS_GET_DATA;
llcc_cmd_buf->llcc_miss_req.get_req.buf_ptr = (u8 *)buf_shm.paddr;
llcc_cmd_buf->llcc_miss_req.get_req.buf_size = bufsize;
llcc_cmd_buf->llcc_miss_req.get_req.type = 1;
llcc_cmd_buf->req_size = sizeof(struct llcc_miss_get_req);
qtee_shmbridge_flush_shm_buf(&buf_shm);
ret = send_llcc_miss_profiling_command(llcc_cmd_buf);
if (ret) {
pr_err("send_llcc_miss_profiling_command failed\n");
goto err;
}
qtee_shmbridge_inv_shm_buf(&buf_shm);
memcpy(llcc_miss->data, (char *)buf_shm.vaddr, sizeof(*llcc_miss->data));
magic = llcc_miss->data->magic;
if (magic != DDR_OUT_BUF_MAGIC) {
pr_err("Expected magic value is %x but got %x\n", DDR_OUT_BUF_MAGIC, magic);
goto err;
}
mutex_lock(&llcc_miss->lock);
for (i = 0; i < MAX_CONCURRENT_MASTERS; i++) {
m = llcc_miss->data->master_buf[i].master_id;
if (m >= MAX_MASTER)
continue;
mdata[m].miss_data[mdata[m].curr_idx].ts = llcc_miss->data->qtime;
mdata[m].miss_data[mdata[m].curr_idx].measured_miss_rate =
llcc_miss->data->master_buf[i].miss_info;
mdata[m].unread_samples = min(++mdata[m].unread_samples, llcc_miss->max_samples);
mdata[m].curr_idx = (mdata[m].curr_idx + 1) % llcc_miss->max_samples;
}
trace_memory_miss_last_sample(llcc_miss->data->qtime,
&llcc_miss->data->master_buf[0],
&llcc_miss->data->master_buf[1]);
mutex_unlock(&llcc_miss->lock);
err:
qtee_shmbridge_free_shm(&buf_shm);
kfree(llcc_cmd_buf);
}
static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
{
ktime_t now = ktime_get();
queue_work(llcc_miss->wq, &llcc_miss->work);
hrtimer_forward(timer, now, ms_to_ktime(SAMPLE_MS));
return HRTIMER_RESTART;
}
static int llcc_miss_create_fs_entries(void)
{
int i;
struct dentry *ret, *master_dir;
llcc_miss_dir = debugfs_create_dir("llcc_miss", 0);
if (IS_ERR(llcc_miss_dir)) {
pr_err("Debugfs directory creation failed for llcc_miss\n");
return PTR_ERR(llcc_miss_dir);
}
for (i = 0; i < MAX_MASTER; i++) {
master_dir = debugfs_create_dir(master_names[i], llcc_miss_dir);
if (IS_ERR(master_dir)) {
pr_err("Debugfs directory creation failed for %s\n", master_names[i]);
goto error_cleanup;
}
ret = debugfs_create_file("show_last_samples", 0400, master_dir,
master_names[i], &show_last_samples_ops);
if (IS_ERR(ret)) {
pr_err("Debugfs file creation failed for show_last_samples\n");
goto error_cleanup;
}
ret = debugfs_create_file("enable", 0644, master_dir,
master_names[i], &set_mon_enabled_ops);
if (IS_ERR(ret)) {
pr_err("Debugfs file creation failed for enable\n");
goto error_cleanup;
}
}
return 0;
error_cleanup:
for (; i >= 0; i--)
debugfs_remove_recursive(debugfs_lookup(master_names[i], llcc_miss_dir));
debugfs_remove_recursive(llcc_miss_dir);
return -ENOENT;
}
static int __init qcom_llcc_miss_init(void)
{
int ret, i, j;
llcc_miss = kzalloc(sizeof(*llcc_miss), GFP_KERNEL);
if (!llcc_miss)
return -ENOMEM;
llcc_miss->data = kzalloc(sizeof(*llcc_miss->data), GFP_KERNEL);
if (!llcc_miss->data) {
kfree(llcc_miss);
return -ENOMEM;
}
for (i = 0; i < MAX_MASTER; i++)
llcc_miss->available_masters |= BIT(i);
ret = llcc_miss_create_fs_entries();
if (ret < 0)
goto err;
/*
* to get no of hex char in a line multiplying size of struct miss_sample by 2
* and adding 1 for tab and 1 for newline.
* output format is qtime followed by miss data in hexa,example -> 32c7bd2 a
*/
llcc_miss->size_of_line = sizeof(struct miss_sample) * 2 + 2;
llcc_miss->max_samples = PAGE_SIZE / llcc_miss->size_of_line;
for (i = 0; i < MAX_MASTER; i++) {
mdata[i].miss_data = kcalloc(llcc_miss->max_samples,
sizeof(struct miss_sample), GFP_KERNEL);
if (!mdata[i].miss_data) {
ret = -ENOMEM;
goto debugfs_file_err;
}
}
mutex_init(&llcc_miss->lock);
hrtimer_init(&llcc_miss->hrtimer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
llcc_miss->hrtimer.function = hrtimer_handler;
llcc_miss->wq = create_freezable_workqueue("llcc_miss_wq");
if (!llcc_miss->wq) {
pr_err("Couldn't create llcc_miss workqueue.\n");
ret = -ENOMEM;
goto debugfs_file_err;
}
INIT_WORK(&llcc_miss->work, &llcc_miss_update_work);
return ret;
debugfs_file_err:
for (j = 0; j < i; j++)
kfree(mdata[j].miss_data);
debugfs_remove_recursive(llcc_miss_dir);
err:
kfree(llcc_miss->data);
kfree(llcc_miss);
return ret;
}
module_init(qcom_llcc_miss_init);
MODULE_DESCRIPTION("QCOM LLCC_MISS driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define CREATE_TRACE_POINTS
#include "trace-bus-prof.h"
EXPORT_TRACEPOINT_SYMBOL(memory_miss_last_sample);
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM bus_prof
#if !defined(_TRACE_BUS_PROF_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_BUS_PROF_H
#include "bus_prof.h"
#include <linux/tracepoint.h>
TRACE_EVENT(memory_miss_last_sample,
TP_PROTO(u64 qtime, struct llcc_miss_buf *master_buf0, struct llcc_miss_buf *master_buf1),
TP_ARGS(qtime, master_buf0, master_buf1),
TP_STRUCT__entry(
__field(u64, qtime)
__field(u8, master1)
__field(u16, miss1)
__field(u8, master2)
__field(u16, miss2)
),
TP_fast_assign(
__entry->qtime = qtime;
__entry->master1 = master_buf0->master_id;
__entry->miss1 = master_buf0->miss_info;
__entry->master2 = master_buf1->master_id;
__entry->miss2 = master_buf1->miss_info;
),
TP_printk("qtime=%llu master1=%u miss1=%u master2=%u miss2=%u",
__entry->qtime,
__entry->master1,
__entry->miss1,
__entry->master2,
__entry->miss2)
);
#endif /* _TRACE_BUS_PROF_H */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH ../../drivers/soc/qcom/dcvs
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace-bus-prof
#include <trace/define_trace.h>

View File

@ -2851,6 +2851,9 @@ static int smcinvoke_probe(struct platform_device *pdev)
unsigned int count = 1;
int rc = 0;
if (!qcom_scm_is_available())
return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "qcom_scm is not up!\n");
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rc) {
pr_err("dma_set_mask_and_coherent failed %d\n", rc);

View File

@ -119,6 +119,8 @@ extern int qcom_scm_pas_shutdown_retry(u32 peripheral);
extern bool qcom_scm_pas_supported(u32 peripheral);
extern int qcom_scm_get_sec_dump_state(u32 *dump_state);
extern int qcom_scm_get_llcc_missrate(phys_addr_t in_buf, size_t in_buf_size,
phys_addr_t out_buf, size_t out_buf_size);
extern int qcom_scm_assign_dump_table_region(bool is_assign, phys_addr_t addr, size_t size);
extern int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out);

View File

@ -54,6 +54,8 @@ msm_geni_serial.ko
msm_rtb.ko
mem_buf.ko
mem_buf_dev.ko
qseecom-mod.ko
smcinvoke_mod.ko
pinctrl-neo.ko
pinctrl-msm.ko
phy-generic.ko

View File

@ -59,6 +59,7 @@ nvmem_qcom-spmi-sdam.ko
pinctrl-spmi-gpio.ko
qcom-spmi-temp-alarm.ko
clk-spmi-pmic-div.ko
qcom_pm8008-regulator.ko
sdhci-msm.ko
core_hang_detect.ko
kryo_arm64_edac.ko