mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
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>
This commit is contained in:
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
static DEFINE_IDR(icc_idr);
|
static DEFINE_IDR(icc_idr);
|
||||||
static LIST_HEAD(icc_providers);
|
static LIST_HEAD(icc_providers);
|
||||||
|
static int providers_count;
|
||||||
|
static bool synced_state;
|
||||||
static DEFINE_MUTEX(icc_lock);
|
static DEFINE_MUTEX(icc_lock);
|
||||||
static struct dentry *icc_debugfs_dir;
|
static struct dentry *icc_debugfs_dir;
|
||||||
|
|
||||||
@@ -267,6 +269,12 @@ static int aggregate_requests(struct icc_node *node)
|
|||||||
}
|
}
|
||||||
p->aggregate(node, r->tag, avg_bw, peak_bw,
|
p->aggregate(node, r->tag, avg_bw, peak_bw,
|
||||||
&node->avg_bw, &node->peak_bw);
|
&node->avg_bw, &node->peak_bw);
|
||||||
|
|
||||||
|
/* during boot use the initial bandwidth as a floor value */
|
||||||
|
if (!synced_state) {
|
||||||
|
node->avg_bw = max(node->avg_bw, node->init_avg);
|
||||||
|
node->peak_bw = max(node->peak_bw, node->init_peak);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -958,6 +966,19 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
|
|||||||
node->provider = provider;
|
node->provider = provider;
|
||||||
list_add_tail(&node->node_list, &provider->nodes);
|
list_add_tail(&node->node_list, &provider->nodes);
|
||||||
|
|
||||||
|
/* get the initial bandwidth values and sync them with hardware */
|
||||||
|
if (provider->get_bw) {
|
||||||
|
provider->get_bw(node, &node->init_avg, &node->init_peak);
|
||||||
|
} else {
|
||||||
|
node->init_avg = INT_MAX;
|
||||||
|
node->init_peak = INT_MAX;
|
||||||
|
}
|
||||||
|
node->avg_bw = node->init_avg;
|
||||||
|
node->peak_bw = node->init_peak;
|
||||||
|
provider->set(node, node);
|
||||||
|
node->avg_bw = 0;
|
||||||
|
node->peak_bw = 0;
|
||||||
|
|
||||||
mutex_unlock(&icc_lock);
|
mutex_unlock(&icc_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(icc_node_add);
|
EXPORT_SYMBOL_GPL(icc_node_add);
|
||||||
@@ -1053,8 +1074,54 @@ int icc_provider_del(struct icc_provider *provider)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(icc_provider_del);
|
EXPORT_SYMBOL_GPL(icc_provider_del);
|
||||||
|
|
||||||
|
static int of_count_icc_providers(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct device_node *child;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for_each_available_child_of_node(np, child) {
|
||||||
|
if (of_property_read_bool(child, "#interconnect-cells"))
|
||||||
|
count++;
|
||||||
|
count += of_count_icc_providers(child);
|
||||||
|
}
|
||||||
|
of_node_put(np);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icc_sync_state(struct device *dev)
|
||||||
|
{
|
||||||
|
struct icc_provider *p;
|
||||||
|
struct icc_node *n;
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count < providers_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&icc_lock);
|
||||||
|
synced_state = true;
|
||||||
|
list_for_each_entry(p, &icc_providers, provider_list) {
|
||||||
|
dev_dbg(p->dev, "interconnect provider is in synced state\n");
|
||||||
|
list_for_each_entry(n, &p->nodes, node_list) {
|
||||||
|
if (n->init_avg || n->init_peak) {
|
||||||
|
aggregate_requests(n);
|
||||||
|
p->set(n, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&icc_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(icc_sync_state);
|
||||||
|
|
||||||
static int __init icc_init(void)
|
static int __init icc_init(void)
|
||||||
{
|
{
|
||||||
|
struct device_node *root = of_find_node_by_path("/");
|
||||||
|
|
||||||
|
providers_count = of_count_icc_providers(root);
|
||||||
|
of_node_put(root);
|
||||||
|
|
||||||
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
|
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
|
||||||
debugfs_create_file("interconnect_summary", 0444,
|
debugfs_create_file("interconnect_summary", 0444,
|
||||||
icc_debugfs_dir, NULL, &icc_summary_fops);
|
icc_debugfs_dir, NULL, &icc_summary_fops);
|
||||||
|
@@ -322,6 +322,7 @@ static struct platform_driver osm_l3_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "osm-l3",
|
.name = "osm-l3",
|
||||||
.of_match_table = osm_l3_of_match,
|
.of_match_table = osm_l3_of_match,
|
||||||
|
.sync_state = icc_sync_state,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(osm_l3_driver);
|
module_platform_driver(osm_l3_driver);
|
||||||
|
@@ -633,6 +633,7 @@ static struct platform_driver qnoc_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "qnoc-sc7180",
|
.name = "qnoc-sc7180",
|
||||||
.of_match_table = qnoc_of_match,
|
.of_match_table = qnoc_of_match,
|
||||||
|
.sync_state = icc_sync_state,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(qnoc_driver);
|
module_platform_driver(qnoc_driver);
|
||||||
|
@@ -559,6 +559,7 @@ static struct platform_driver qnoc_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "qnoc-sdm845",
|
.name = "qnoc-sdm845",
|
||||||
.of_match_table = qnoc_of_match,
|
.of_match_table = qnoc_of_match,
|
||||||
|
.sync_state = icc_sync_state,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(qnoc_driver);
|
module_platform_driver(qnoc_driver);
|
||||||
|
@@ -49,6 +49,7 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
|
|||||||
* @aggregate: pointer to device specific aggregate operation function
|
* @aggregate: pointer to device specific aggregate operation function
|
||||||
* @pre_aggregate: pointer to device specific function that is called
|
* @pre_aggregate: pointer to device specific function that is called
|
||||||
* before the aggregation begins (optional)
|
* before the aggregation begins (optional)
|
||||||
|
* @get_bw: pointer to device specific function to get current bandwidth
|
||||||
* @xlate: provider-specific callback for mapping nodes from phandle arguments
|
* @xlate: provider-specific callback for mapping nodes from phandle arguments
|
||||||
* @xlate_extended: vendor-specific callback for mapping node data from phandle arguments
|
* @xlate_extended: vendor-specific callback for mapping node data from phandle arguments
|
||||||
* @dev: the device this interconnect provider belongs to
|
* @dev: the device this interconnect provider belongs to
|
||||||
@@ -63,6 +64,7 @@ struct icc_provider {
|
|||||||
int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
|
int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
|
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
|
||||||
void (*pre_aggregate)(struct icc_node *node);
|
void (*pre_aggregate)(struct icc_node *node);
|
||||||
|
int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
|
||||||
struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
|
struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
|
||||||
struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
|
struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -86,6 +88,8 @@ struct icc_provider {
|
|||||||
* @req_list: a list of QoS constraint requests associated with this node
|
* @req_list: a list of QoS constraint requests associated with this node
|
||||||
* @avg_bw: aggregated value of average bandwidth requests from all consumers
|
* @avg_bw: aggregated value of average bandwidth requests from all consumers
|
||||||
* @peak_bw: aggregated value of peak bandwidth requests from all consumers
|
* @peak_bw: aggregated value of peak bandwidth requests from all consumers
|
||||||
|
* @init_avg: average bandwidth value that is read from the hardware during init
|
||||||
|
* @init_peak: peak bandwidth value that is read from the hardware during init
|
||||||
* @data: pointer to private data
|
* @data: pointer to private data
|
||||||
*/
|
*/
|
||||||
struct icc_node {
|
struct icc_node {
|
||||||
@@ -102,6 +106,8 @@ struct icc_node {
|
|||||||
struct hlist_head req_list;
|
struct hlist_head req_list;
|
||||||
u32 avg_bw;
|
u32 avg_bw;
|
||||||
u32 peak_bw;
|
u32 peak_bw;
|
||||||
|
u32 init_avg;
|
||||||
|
u32 init_peak;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,6 +125,7 @@ int icc_nodes_remove(struct icc_provider *provider);
|
|||||||
int icc_provider_add(struct icc_provider *provider);
|
int icc_provider_add(struct icc_provider *provider);
|
||||||
int icc_provider_del(struct icc_provider *provider);
|
int icc_provider_del(struct icc_provider *provider);
|
||||||
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
|
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
|
||||||
|
void icc_sync_state(struct device *dev);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user