Loading drivers/interconnect/core.c +67 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ static DEFINE_IDR(icc_idr); static LIST_HEAD(icc_providers); static int providers_count; static bool synced_state; static DEFINE_MUTEX(icc_lock); static struct dentry *icc_debugfs_dir; Loading Loading @@ -267,6 +269,12 @@ static int aggregate_requests(struct icc_node *node) } p->aggregate(node, r->tag, avg_bw, 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; Loading Loading @@ -958,6 +966,19 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider) node->provider = provider; 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); } EXPORT_SYMBOL_GPL(icc_node_add); Loading Loading @@ -1053,8 +1074,54 @@ int icc_provider_del(struct icc_provider *provider) } 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) { 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); debugfs_create_file("interconnect_summary", 0444, icc_debugfs_dir, NULL, &icc_summary_fops); Loading drivers/interconnect/qcom/osm-l3.c +1 −0 Original line number Diff line number Diff line Loading @@ -322,6 +322,7 @@ static struct platform_driver osm_l3_driver = { .driver = { .name = "osm-l3", .of_match_table = osm_l3_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(osm_l3_driver); Loading drivers/interconnect/qcom/sc7180.c +1 −0 Original line number Diff line number Diff line Loading @@ -633,6 +633,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-sc7180", .of_match_table = qnoc_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(qnoc_driver); Loading drivers/interconnect/qcom/sdm845.c +1 −0 Original line number Diff line number Diff line Loading @@ -559,6 +559,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-sdm845", .of_match_table = qnoc_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(qnoc_driver); Loading include/linux/interconnect-provider.h +7 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, * @aggregate: pointer to device specific aggregate operation function * @pre_aggregate: pointer to device specific function that is called * 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_extended: vendor-specific callback for mapping node data from phandle arguments * @dev: the device this interconnect provider belongs to Loading @@ -63,6 +64,7 @@ struct icc_provider { int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak); 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_data* (*xlate_extended)(struct of_phandle_args *spec, void *data); struct device *dev; Loading @@ -86,6 +88,8 @@ struct icc_provider { * @req_list: a list of QoS constraint requests associated with this node * @avg_bw: aggregated value of average 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 */ struct icc_node { Loading @@ -102,6 +106,8 @@ struct icc_node { struct hlist_head req_list; u32 avg_bw; u32 peak_bw; u32 init_avg; u32 init_peak; void *data; }; Loading @@ -119,6 +125,7 @@ int icc_nodes_remove(struct icc_provider *provider); int icc_provider_add(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); void icc_sync_state(struct device *dev); #else Loading Loading
drivers/interconnect/core.c +67 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ static DEFINE_IDR(icc_idr); static LIST_HEAD(icc_providers); static int providers_count; static bool synced_state; static DEFINE_MUTEX(icc_lock); static struct dentry *icc_debugfs_dir; Loading Loading @@ -267,6 +269,12 @@ static int aggregate_requests(struct icc_node *node) } p->aggregate(node, r->tag, avg_bw, 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; Loading Loading @@ -958,6 +966,19 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider) node->provider = provider; 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); } EXPORT_SYMBOL_GPL(icc_node_add); Loading Loading @@ -1053,8 +1074,54 @@ int icc_provider_del(struct icc_provider *provider) } 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) { 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); debugfs_create_file("interconnect_summary", 0444, icc_debugfs_dir, NULL, &icc_summary_fops); Loading
drivers/interconnect/qcom/osm-l3.c +1 −0 Original line number Diff line number Diff line Loading @@ -322,6 +322,7 @@ static struct platform_driver osm_l3_driver = { .driver = { .name = "osm-l3", .of_match_table = osm_l3_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(osm_l3_driver); Loading
drivers/interconnect/qcom/sc7180.c +1 −0 Original line number Diff line number Diff line Loading @@ -633,6 +633,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-sc7180", .of_match_table = qnoc_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(qnoc_driver); Loading
drivers/interconnect/qcom/sdm845.c +1 −0 Original line number Diff line number Diff line Loading @@ -559,6 +559,7 @@ static struct platform_driver qnoc_driver = { .driver = { .name = "qnoc-sdm845", .of_match_table = qnoc_of_match, .sync_state = icc_sync_state, }, }; module_platform_driver(qnoc_driver); Loading
include/linux/interconnect-provider.h +7 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, * @aggregate: pointer to device specific aggregate operation function * @pre_aggregate: pointer to device specific function that is called * 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_extended: vendor-specific callback for mapping node data from phandle arguments * @dev: the device this interconnect provider belongs to Loading @@ -63,6 +64,7 @@ struct icc_provider { int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak); 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_data* (*xlate_extended)(struct of_phandle_args *spec, void *data); struct device *dev; Loading @@ -86,6 +88,8 @@ struct icc_provider { * @req_list: a list of QoS constraint requests associated with this node * @avg_bw: aggregated value of average 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 */ struct icc_node { Loading @@ -102,6 +106,8 @@ struct icc_node { struct hlist_head req_list; u32 avg_bw; u32 peak_bw; u32 init_avg; u32 init_peak; void *data; }; Loading @@ -119,6 +125,7 @@ int icc_nodes_remove(struct icc_provider *provider); int icc_provider_add(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); void icc_sync_state(struct device *dev); #else Loading