Skip to content

Commit 628fdbc

Browse files
author
Georgi Djakov
committed
Merge branch 'icc-syncstate' into icc-next
* icc-syncstate: interconnect: Add get_bw() callback interconnect: Add sync state support interconnect: qcom: Use icc_sync_state Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
2 parents b1a367b + 7d3b0b0 commit 628fdbc

5 files changed

Lines changed: 77 additions & 0 deletions

File tree

drivers/interconnect/core.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
static DEFINE_IDR(icc_idr);
2828
static LIST_HEAD(icc_providers);
29+
static int providers_count;
30+
static bool synced_state;
2931
static DEFINE_MUTEX(icc_lock);
3032
static struct dentry *icc_debugfs_dir;
3133

@@ -267,6 +269,12 @@ static int aggregate_requests(struct icc_node *node)
267269
}
268270
p->aggregate(node, r->tag, avg_bw, peak_bw,
269271
&node->avg_bw, &node->peak_bw);
272+
273+
/* during boot use the initial bandwidth as a floor value */
274+
if (!synced_state) {
275+
node->avg_bw = max(node->avg_bw, node->init_avg);
276+
node->peak_bw = max(node->peak_bw, node->init_peak);
277+
}
270278
}
271279

272280
return 0;
@@ -958,6 +966,19 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
958966
node->provider = provider;
959967
list_add_tail(&node->node_list, &provider->nodes);
960968

969+
/* get the initial bandwidth values and sync them with hardware */
970+
if (provider->get_bw) {
971+
provider->get_bw(node, &node->init_avg, &node->init_peak);
972+
} else {
973+
node->init_avg = INT_MAX;
974+
node->init_peak = INT_MAX;
975+
}
976+
node->avg_bw = node->init_avg;
977+
node->peak_bw = node->init_peak;
978+
provider->set(node, node);
979+
node->avg_bw = 0;
980+
node->peak_bw = 0;
981+
961982
mutex_unlock(&icc_lock);
962983
}
963984
EXPORT_SYMBOL_GPL(icc_node_add);
@@ -1053,8 +1074,54 @@ int icc_provider_del(struct icc_provider *provider)
10531074
}
10541075
EXPORT_SYMBOL_GPL(icc_provider_del);
10551076

1077+
static int of_count_icc_providers(struct device_node *np)
1078+
{
1079+
struct device_node *child;
1080+
int count = 0;
1081+
1082+
for_each_available_child_of_node(np, child) {
1083+
if (of_property_read_bool(child, "#interconnect-cells"))
1084+
count++;
1085+
count += of_count_icc_providers(child);
1086+
}
1087+
of_node_put(np);
1088+
1089+
return count;
1090+
}
1091+
1092+
void icc_sync_state(struct device *dev)
1093+
{
1094+
struct icc_provider *p;
1095+
struct icc_node *n;
1096+
static int count;
1097+
1098+
count++;
1099+
1100+
if (count < providers_count)
1101+
return;
1102+
1103+
mutex_lock(&icc_lock);
1104+
synced_state = true;
1105+
list_for_each_entry(p, &icc_providers, provider_list) {
1106+
dev_dbg(p->dev, "interconnect provider is in synced state\n");
1107+
list_for_each_entry(n, &p->nodes, node_list) {
1108+
if (n->init_avg || n->init_peak) {
1109+
aggregate_requests(n);
1110+
p->set(n, n);
1111+
}
1112+
}
1113+
}
1114+
mutex_unlock(&icc_lock);
1115+
}
1116+
EXPORT_SYMBOL_GPL(icc_sync_state);
1117+
10561118
static int __init icc_init(void)
10571119
{
1120+
struct device_node *root = of_find_node_by_path("/");
1121+
1122+
providers_count = of_count_icc_providers(root);
1123+
of_node_put(root);
1124+
10581125
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
10591126
debugfs_create_file("interconnect_summary", 0444,
10601127
icc_debugfs_dir, NULL, &icc_summary_fops);

drivers/interconnect/qcom/osm-l3.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ static struct platform_driver osm_l3_driver = {
322322
.driver = {
323323
.name = "osm-l3",
324324
.of_match_table = osm_l3_of_match,
325+
.sync_state = icc_sync_state,
325326
},
326327
};
327328
module_platform_driver(osm_l3_driver);

drivers/interconnect/qcom/sc7180.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ static struct platform_driver qnoc_driver = {
633633
.driver = {
634634
.name = "qnoc-sc7180",
635635
.of_match_table = qnoc_of_match,
636+
.sync_state = icc_sync_state,
636637
},
637638
};
638639
module_platform_driver(qnoc_driver);

drivers/interconnect/qcom/sdm845.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ static struct platform_driver qnoc_driver = {
559559
.driver = {
560560
.name = "qnoc-sdm845",
561561
.of_match_table = qnoc_of_match,
562+
.sync_state = icc_sync_state,
562563
},
563564
};
564565
module_platform_driver(qnoc_driver);

include/linux/interconnect-provider.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
4949
* @aggregate: pointer to device specific aggregate operation function
5050
* @pre_aggregate: pointer to device specific function that is called
5151
* before the aggregation begins (optional)
52+
* @get_bw: pointer to device specific function to get current bandwidth
5253
* @xlate: provider-specific callback for mapping nodes from phandle arguments
5354
* @xlate_extended: vendor-specific callback for mapping node data from phandle arguments
5455
* @dev: the device this interconnect provider belongs to
@@ -63,6 +64,7 @@ struct icc_provider {
6364
int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
6465
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
6566
void (*pre_aggregate)(struct icc_node *node);
67+
int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
6668
struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
6769
struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
6870
struct device *dev;
@@ -86,6 +88,8 @@ struct icc_provider {
8688
* @req_list: a list of QoS constraint requests associated with this node
8789
* @avg_bw: aggregated value of average bandwidth requests from all consumers
8890
* @peak_bw: aggregated value of peak bandwidth requests from all consumers
91+
* @init_avg: average bandwidth value that is read from the hardware during init
92+
* @init_peak: peak bandwidth value that is read from the hardware during init
8993
* @data: pointer to private data
9094
*/
9195
struct icc_node {
@@ -102,6 +106,8 @@ struct icc_node {
102106
struct hlist_head req_list;
103107
u32 avg_bw;
104108
u32 peak_bw;
109+
u32 init_avg;
110+
u32 init_peak;
105111
void *data;
106112
};
107113

@@ -119,6 +125,7 @@ int icc_nodes_remove(struct icc_provider *provider);
119125
int icc_provider_add(struct icc_provider *provider);
120126
int icc_provider_del(struct icc_provider *provider);
121127
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
128+
void icc_sync_state(struct device *dev);
122129

123130
#else
124131

0 commit comments

Comments
 (0)