Skip to content

Commit eb59eca

Browse files
jhovoldGeorgi Djakov
authored andcommitted
interconnect: fix provider registration API
The current interconnect provider interface is inherently racy as providers are expected to be added before being fully initialised. Specifically, nodes are currently not added and the provider data is not initialised until after registering the provider which can cause racing DT lookups to fail. Add a new provider API which will be used to fix up the interconnect drivers. The old API is reimplemented using the new interface and will be removed once all drivers have been fixed. Fixes: 11f1cec ("interconnect: Add generic on-chip interconnect API") Fixes: 87e3031 ("interconnect: Allow endpoints translation via DT") Cc: [email protected] # 5.1 Reviewed-by: Konrad Dybcio <[email protected]> Signed-off-by: Johan Hovold <[email protected]> Tested-by: Luca Ceresoli <[email protected]> # i.MX8MP MSC SM2-MB-EP1 Board Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Georgi Djakov <[email protected]>
1 parent e0e7089 commit eb59eca

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

drivers/interconnect/core.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,44 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider)
10331033
EXPORT_SYMBOL_GPL(icc_nodes_remove);
10341034

10351035
/**
1036-
* icc_provider_add() - add a new interconnect provider
1037-
* @provider: the interconnect provider that will be added into topology
1036+
* icc_provider_init() - initialize a new interconnect provider
1037+
* @provider: the interconnect provider to initialize
1038+
*
1039+
* Must be called before adding nodes to the provider.
1040+
*/
1041+
void icc_provider_init(struct icc_provider *provider)
1042+
{
1043+
WARN_ON(!provider->set);
1044+
1045+
INIT_LIST_HEAD(&provider->nodes);
1046+
}
1047+
EXPORT_SYMBOL_GPL(icc_provider_init);
1048+
1049+
/**
1050+
* icc_provider_register() - register a new interconnect provider
1051+
* @provider: the interconnect provider to register
10381052
*
10391053
* Return: 0 on success, or an error code otherwise
10401054
*/
1041-
int icc_provider_add(struct icc_provider *provider)
1055+
int icc_provider_register(struct icc_provider *provider)
10421056
{
1043-
if (WARN_ON(!provider->set))
1044-
return -EINVAL;
10451057
if (WARN_ON(!provider->xlate && !provider->xlate_extended))
10461058
return -EINVAL;
10471059

10481060
mutex_lock(&icc_lock);
1049-
1050-
INIT_LIST_HEAD(&provider->nodes);
10511061
list_add_tail(&provider->provider_list, &icc_providers);
1052-
10531062
mutex_unlock(&icc_lock);
10541063

1055-
dev_dbg(provider->dev, "interconnect provider added to topology\n");
1064+
dev_dbg(provider->dev, "interconnect provider registered\n");
10561065

10571066
return 0;
10581067
}
1059-
EXPORT_SYMBOL_GPL(icc_provider_add);
1068+
EXPORT_SYMBOL_GPL(icc_provider_register);
10601069

10611070
/**
1062-
* icc_provider_del() - delete previously added interconnect provider
1063-
* @provider: the interconnect provider that will be removed from topology
1071+
* icc_provider_deregister() - deregister an interconnect provider
1072+
* @provider: the interconnect provider to deregister
10641073
*/
1065-
void icc_provider_del(struct icc_provider *provider)
1074+
void icc_provider_deregister(struct icc_provider *provider)
10661075
{
10671076
mutex_lock(&icc_lock);
10681077
WARN_ON(provider->users);
1069-
WARN_ON(!list_empty(&provider->nodes));
10701078

10711079
list_del(&provider->provider_list);
10721080
mutex_unlock(&icc_lock);
10731081
}
1082+
EXPORT_SYMBOL_GPL(icc_provider_deregister);
1083+
1084+
int icc_provider_add(struct icc_provider *provider)
1085+
{
1086+
icc_provider_init(provider);
1087+
1088+
return icc_provider_register(provider);
1089+
}
1090+
EXPORT_SYMBOL_GPL(icc_provider_add);
1091+
1092+
void icc_provider_del(struct icc_provider *provider)
1093+
{
1094+
WARN_ON(!list_empty(&provider->nodes));
1095+
1096+
icc_provider_deregister(provider);
1097+
}
10741098
EXPORT_SYMBOL_GPL(icc_provider_del);
10751099

10761100
static const struct of_device_id __maybe_unused ignore_list[] = {

include/linux/interconnect-provider.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst);
122122
void icc_node_add(struct icc_node *node, struct icc_provider *provider);
123123
void icc_node_del(struct icc_node *node);
124124
int icc_nodes_remove(struct icc_provider *provider);
125+
void icc_provider_init(struct icc_provider *provider);
126+
int icc_provider_register(struct icc_provider *provider);
127+
void icc_provider_deregister(struct icc_provider *provider);
125128
int icc_provider_add(struct icc_provider *provider);
126129
void icc_provider_del(struct icc_provider *provider);
127130
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
@@ -167,6 +170,15 @@ static inline int icc_nodes_remove(struct icc_provider *provider)
167170
return -ENOTSUPP;
168171
}
169172

173+
static inline void icc_provider_init(struct icc_provider *provider) { }
174+
175+
static inline int icc_provider_register(struct icc_provider *provider)
176+
{
177+
return -ENOTSUPP;
178+
}
179+
180+
static inline void icc_provider_deregister(struct icc_provider *provider) { }
181+
170182
static inline int icc_provider_add(struct icc_provider *provider)
171183
{
172184
return -ENOTSUPP;

0 commit comments

Comments
 (0)