summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-11-09 09:58:56 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-11-09 09:58:56 -0800
commitd36a884a1ef5b6808bea1f402fdbe976f85d993c (patch)
treedaa55efe2b6dd99a3bbfb21f2de0320824652534
parent59b028f31db3a73cf66f6947eece80d141ad36e4 (diff)
parent16d78cda70e116fb9cb61790b93b0c85e107ba4b (diff)
Merge "soc: qcom: msm_bus: Add debug logging for max bandwidth votes"
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_adhoc.h5
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c12
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c124
-rw-r--r--include/trace/events/trace_msm_bus.h40
4 files changed, 177 insertions, 4 deletions
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h b/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
index 7440e0473e8b..5906e2ed8532 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017, The Linux Foundation. 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 and
@@ -50,9 +50,12 @@ struct nodebw {
uint64_t sum_ab;
uint64_t last_sum_ab;
uint64_t max_ib;
+ uint64_t max_ab;
uint64_t cur_clk_hz;
uint32_t util_used;
uint32_t vrail_used;
+ const char *max_ab_cl_name;
+ const char *max_ib_cl_name;
};
struct msm_bus_fab_device_type {
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
index aafe82f59b9a..4ed3e65c0293 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
@@ -549,6 +549,7 @@ static uint64_t aggregate_bus_req(struct msm_bus_node_device_type *bus_dev,
struct msm_bus_node_device_type *fab_dev = NULL;
uint32_t agg_scheme;
uint64_t max_ib = 0;
+ uint64_t max_ab = 0;
uint64_t sum_ab = 0;
if (!bus_dev || !to_msm_bus_node(bus_dev->node_info->bus_device)) {
@@ -556,14 +557,25 @@ static uint64_t aggregate_bus_req(struct msm_bus_node_device_type *bus_dev,
goto exit_agg_bus_req;
}
+ bus_dev->node_bw[ctx].max_ib_cl_name = NULL;
+ bus_dev->node_bw[ctx].max_ab_cl_name = NULL;
fab_dev = to_msm_bus_node(bus_dev->node_info->bus_device);
for (i = 0; i < bus_dev->num_lnodes; i++) {
+ if (bus_dev->lnode_list[i].lnode_ib[ctx] > max_ib)
+ bus_dev->node_bw[ctx].max_ib_cl_name =
+ bus_dev->lnode_list[i].cl_name;
max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]);
+ if (bus_dev->lnode_list[i].lnode_ab[ctx] > max_ab) {
+ max_ab = bus_dev->lnode_list[i].lnode_ab[ctx];
+ bus_dev->node_bw[ctx].max_ab_cl_name =
+ bus_dev->lnode_list[i].cl_name;
+ }
sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx];
}
bus_dev->node_bw[ctx].sum_ab = sum_ab;
bus_dev->node_bw[ctx].max_ib = max_ib;
+ bus_dev->node_bw[ctx].max_ab = max_ab;
if (bus_dev->node_info->agg_params.agg_scheme != AGG_SCHEME_NONE)
agg_scheme = bus_dev->node_info->agg_params.agg_scheme;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
index 305f31f31bf8..7288c79de428 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, Linux Foundation. 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 and
@@ -24,6 +24,8 @@
#include "msm_bus_noc.h"
#include "msm_bus_bimc.h"
+static LIST_HEAD(fabdev_list);
+
static int msm_bus_dev_init_qos(struct device *dev, void *data);
ssize_t bw_show(struct device *dev, struct device_attribute *attr,
@@ -431,6 +433,68 @@ static int msm_bus_agg_fab_clks(struct msm_bus_node_device_type *bus_dev)
return ret;
}
+static void msm_bus_log_fab_max_votes(struct msm_bus_node_device_type *bus_dev)
+{
+ int ctx;
+ struct timespec ts;
+ uint32_t vrail_comp = 0;
+ struct msm_bus_node_device_type *node;
+ uint64_t max_ib, max_ib_temp[NUM_CTX];
+
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ max_ib_temp[ctx] = 0;
+ bus_dev->node_bw[ctx].max_ib = 0;
+ bus_dev->node_bw[ctx].max_ab = 0;
+ bus_dev->node_bw[ctx].max_ib_cl_name = NULL;
+ bus_dev->node_bw[ctx].max_ab_cl_name = NULL;
+ }
+
+ list_for_each_entry(node, &bus_dev->devlist, dev_link) {
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ max_ib = node->node_bw[ctx].max_ib;
+ vrail_comp = node->node_bw[ctx].vrail_used;
+
+ if (vrail_comp && (vrail_comp != 100)) {
+ max_ib *= 100;
+ max_ib = msm_bus_div64(vrail_comp, max_ib);
+ }
+
+ if (max_ib > max_ib_temp[ctx]) {
+ max_ib_temp[ctx] = max_ib;
+ bus_dev->node_bw[ctx].max_ib =
+ node->node_bw[ctx].max_ib;
+ bus_dev->node_bw[ctx].max_ib_cl_name =
+ node->node_bw[ctx].max_ib_cl_name;
+ }
+
+ if (node->node_bw[ctx].max_ab >
+ bus_dev->node_bw[ctx].max_ab) {
+ bus_dev->node_bw[ctx].max_ab =
+ node->node_bw[ctx].max_ab;
+ bus_dev->node_bw[ctx].max_ab_cl_name =
+ node->node_bw[ctx].max_ab_cl_name;
+ }
+ }
+ }
+
+ ts = ktime_to_timespec(ktime_get());
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ trace_bus_max_votes((int)ts.tv_sec, (int)ts.tv_nsec,
+ bus_dev->node_info->name,
+ ((ctx == ACTIVE_CTX) ? "active" : "sleep"),
+ "ib", bus_dev->node_bw[ctx].max_ib,
+ bus_dev->node_bw[ctx].max_ib_cl_name);
+ }
+
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ trace_bus_max_votes((int)ts.tv_sec, (int)ts.tv_nsec,
+ bus_dev->node_info->name,
+ ((ctx == ACTIVE_CTX) ? "active" : "sleep"),
+ "ab", bus_dev->node_bw[ctx].max_ab,
+ bus_dev->node_bw[ctx].max_ab_cl_name);
+ }
+}
+
int msm_bus_commit_data(struct list_head *clist)
{
int ret = 0;
@@ -440,8 +504,10 @@ int msm_bus_commit_data(struct list_head *clist)
list_for_each_entry(node, clist, link) {
/* Aggregate the bus clocks */
- if (node->node_info->is_fab_dev)
+ if (node->node_info->is_fab_dev) {
msm_bus_agg_fab_clks(node);
+ msm_bus_log_fab_max_votes(node);
+ }
}
list_for_each_entry_safe(node, node_tmp, clist, link) {
@@ -1146,6 +1212,53 @@ int msm_bus_device_remove(struct platform_device *pdev)
return 0;
}
+/**
+ * msm_bus_panic_callback() - panic notification callback function.
+ * This function is invoked when a kernel panic occurs.
+ * @nfb: Notifier block pointer
+ * @event: Value passed unmodified to notifier function
+ * @data: Pointer passed unmodified to notifier function
+ *
+ * Return: NOTIFY_OK
+ */
+static int msm_bus_panic_callback(struct notifier_block *nfb,
+ unsigned long event, void *data)
+{
+ struct msm_bus_node_device_type *bus_node = NULL;
+ unsigned int ctx;
+
+ list_for_each_entry(bus_node, &fabdev_list, dev_link) {
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ if (bus_node->node_bw[ctx].max_ib_cl_name &&
+ bus_node->node_bw[ctx].max_ib) {
+ pr_err("%s: %s: %s max_ib: %llu: client-name: %s\n",
+ __func__, bus_node->node_info->name,
+ ((ctx == ACTIVE_CTX) ? "active" : "sleep"),
+ bus_node->node_bw[ctx].max_ib,
+ bus_node->node_bw[ctx].max_ib_cl_name);
+ }
+ }
+
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ if (bus_node->node_bw[ctx].max_ab_cl_name &&
+ bus_node->node_bw[ctx].max_ab) {
+ pr_err("%s: %s: %s max_ab: %llu: client-name: %s\n",
+ __func__, bus_node->node_info->name,
+ ((ctx == ACTIVE_CTX) ? "active" : "sleep"),
+ bus_node->node_bw[ctx].max_ab,
+ bus_node->node_bw[ctx].max_ab_cl_name);
+ }
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block msm_bus_panic_notifier = {
+ .notifier_call = msm_bus_panic_callback,
+ .priority = 1,
+};
+
static int msm_bus_device_probe(struct platform_device *pdev)
{
unsigned int i, ret;
@@ -1167,6 +1280,7 @@ static int msm_bus_device_probe(struct platform_device *pdev)
for (i = 0; i < pdata->num_devices; i++) {
struct device *node_dev = NULL;
+ struct msm_bus_node_device_type *bus_node = NULL;
node_dev = msm_bus_device_init(&pdata->info[i]);
@@ -1193,6 +1307,9 @@ static int msm_bus_device_probe(struct platform_device *pdev)
__func__, pdata->info[i].node_info->id);
goto exit_device_probe;
}
+
+ bus_node = to_msm_bus_node(node_dev);
+ list_add_tail(&bus_node->dev_link, &fabdev_list);
}
}
@@ -1214,6 +1331,9 @@ static int msm_bus_device_probe(struct platform_device *pdev)
msm_bus_arb_setops_adhoc(&arb_ops);
bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_node_debug);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_bus_panic_notifier);
+
devm_kfree(&pdev->dev, pdata->info);
devm_kfree(&pdev->dev, pdata);
exit_device_probe:
diff --git a/include/trace/events/trace_msm_bus.h b/include/trace/events/trace_msm_bus.h
index d914a9660049..3f56fc1e80fb 100644
--- a/include/trace/events/trace_msm_bus.h
+++ b/include/trace/events/trace_msm_bus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017, The Linux Foundation. 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 and
@@ -72,6 +72,44 @@ TRACE_EVENT(bus_update_request_end,
TP_printk("client-name=%s", __get_str(name))
);
+TRACE_EVENT(bus_max_votes,
+
+ TP_PROTO(int sec, int nsec, const char *bus_name, const char *ctx,
+ const char *bw_type_name, unsigned long long bw,
+ const char *cl_name),
+
+ TP_ARGS(sec, nsec, bus_name, ctx, bw_type_name, bw, cl_name),
+
+ TP_STRUCT__entry(
+ __field(int, sec)
+ __field(int, nsec)
+ __string(bus_name, bus_name)
+ __string(ctx, ctx)
+ __string(bw_type_name, bw_type_name)
+ __field(u64, bw)
+ __string(cl_name, cl_name)
+ ),
+
+ TP_fast_assign(
+ __entry->sec = sec;
+ __entry->nsec = nsec;
+ __assign_str(bus_name, bus_name);
+ __assign_str(ctx, ctx);
+ __assign_str(bw_type_name, bw_type_name);
+ __entry->bw = bw;
+ __assign_str(cl_name, cl_name);
+ ),
+
+ TP_printk("time= %u.%09u %s: %s max_%s: %llu: client-name: %s",
+ __entry->sec,
+ __entry->nsec,
+ __get_str(bus_name),
+ __get_str(ctx),
+ __get_str(bw_type_name),
+ (unsigned long long)__entry->bw,
+ __get_str(cl_name))
+);
+
TRACE_EVENT(bus_bimc_config_limiter,
TP_PROTO(int mas_id, unsigned long long cur_lim_bw),