diff options
author | Mike Turquette <mturquette@linaro.org> | 2012-03-29 17:30:40 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2012-04-24 19:37:39 -0400 |
commit | d1302a36a7f1c33d1a8babc6a510e1401a5e5aed (patch) | |
tree | bcb0d5f659a762764b75720fdada09ac9c548886 /drivers/clk | |
parent | d305fb78f31209596c9135d396a0d3af7ac86947 (diff) |
clk: core: copy parent_names & return error codes
This patch cleans up clk_register and solves a few bugs by teaching
clk_register and __clk_init to return error codes (instead of just NULL)
to better align with the existing clk.h api.
Along with that change this patch also introduces a new behavior whereby
clk_register copies the parent_names array, thus allowing platforms to
declare their parent_names arrays as __initdata.
Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/clk.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ddade8759ea9..8f7c3849c8f6 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -1185,34 +1185,41 @@ EXPORT_SYMBOL_GPL(clk_set_parent); | |||
1185 | * very large numbers of clocks that need to be statically initialized. It is | 1185 | * very large numbers of clocks that need to be statically initialized. It is |
1186 | * a layering violation to include clk-private.h from any code which implements | 1186 | * a layering violation to include clk-private.h from any code which implements |
1187 | * a clock's .ops; as such any statically initialized clock data MUST be in a | 1187 | * a clock's .ops; as such any statically initialized clock data MUST be in a |
1188 | * separate C file from the logic that implements it's operations. | 1188 | * separate C file from the logic that implements it's operations. Returns 0 |
1189 | * on success, otherwise an error code. | ||
1189 | */ | 1190 | */ |
1190 | void __clk_init(struct device *dev, struct clk *clk) | 1191 | int __clk_init(struct device *dev, struct clk *clk) |
1191 | { | 1192 | { |
1192 | int i; | 1193 | int i, ret = 0; |
1193 | struct clk *orphan; | 1194 | struct clk *orphan; |
1194 | struct hlist_node *tmp, *tmp2; | 1195 | struct hlist_node *tmp, *tmp2; |
1195 | 1196 | ||
1196 | if (!clk) | 1197 | if (!clk) |
1197 | return; | 1198 | return -EINVAL; |
1198 | 1199 | ||
1199 | mutex_lock(&prepare_lock); | 1200 | mutex_lock(&prepare_lock); |
1200 | 1201 | ||
1201 | /* check to see if a clock with this name is already registered */ | 1202 | /* check to see if a clock with this name is already registered */ |
1202 | if (__clk_lookup(clk->name)) | 1203 | if (__clk_lookup(clk->name)) { |
1204 | pr_debug("%s: clk %s already initialized\n", | ||
1205 | __func__, clk->name); | ||
1206 | ret = -EEXIST; | ||
1203 | goto out; | 1207 | goto out; |
1208 | } | ||
1204 | 1209 | ||
1205 | /* check that clk_ops are sane. See Documentation/clk.txt */ | 1210 | /* check that clk_ops are sane. See Documentation/clk.txt */ |
1206 | if (clk->ops->set_rate && | 1211 | if (clk->ops->set_rate && |
1207 | !(clk->ops->round_rate && clk->ops->recalc_rate)) { | 1212 | !(clk->ops->round_rate && clk->ops->recalc_rate)) { |
1208 | pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", | 1213 | pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", |
1209 | __func__, clk->name); | 1214 | __func__, clk->name); |
1215 | ret = -EINVAL; | ||
1210 | goto out; | 1216 | goto out; |
1211 | } | 1217 | } |
1212 | 1218 | ||
1213 | if (clk->ops->set_parent && !clk->ops->get_parent) { | 1219 | if (clk->ops->set_parent && !clk->ops->get_parent) { |
1214 | pr_warning("%s: %s must implement .get_parent & .set_parent\n", | 1220 | pr_warning("%s: %s must implement .get_parent & .set_parent\n", |
1215 | __func__, clk->name); | 1221 | __func__, clk->name); |
1222 | ret = -EINVAL; | ||
1216 | goto out; | 1223 | goto out; |
1217 | } | 1224 | } |
1218 | 1225 | ||
@@ -1308,7 +1315,7 @@ void __clk_init(struct device *dev, struct clk *clk) | |||
1308 | out: | 1315 | out: |
1309 | mutex_unlock(&prepare_lock); | 1316 | mutex_unlock(&prepare_lock); |
1310 | 1317 | ||
1311 | return; | 1318 | return ret; |
1312 | } | 1319 | } |
1313 | 1320 | ||
1314 | /** | 1321 | /** |
@@ -1324,29 +1331,63 @@ out: | |||
1324 | * clk_register is the primary interface for populating the clock tree with new | 1331 | * clk_register is the primary interface for populating the clock tree with new |
1325 | * clock nodes. It returns a pointer to the newly allocated struct clk which | 1332 | * clock nodes. It returns a pointer to the newly allocated struct clk which |
1326 | * cannot be dereferenced by driver code but may be used in conjuction with the | 1333 | * cannot be dereferenced by driver code but may be used in conjuction with the |
1327 | * rest of the clock API. | 1334 | * rest of the clock API. In the event of an error clk_register will return an |
1335 | * error code; drivers must test for an error code after calling clk_register. | ||
1328 | */ | 1336 | */ |
1329 | struct clk *clk_register(struct device *dev, const char *name, | 1337 | struct clk *clk_register(struct device *dev, const char *name, |
1330 | const struct clk_ops *ops, struct clk_hw *hw, | 1338 | const struct clk_ops *ops, struct clk_hw *hw, |
1331 | const char **parent_names, u8 num_parents, unsigned long flags) | 1339 | const char **parent_names, u8 num_parents, unsigned long flags) |
1332 | { | 1340 | { |
1341 | int i, ret; | ||
1333 | struct clk *clk; | 1342 | struct clk *clk; |
1334 | 1343 | ||
1335 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); | 1344 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); |
1336 | if (!clk) | 1345 | if (!clk) { |
1337 | return NULL; | 1346 | pr_err("%s: could not allocate clk\n", __func__); |
1347 | ret = -ENOMEM; | ||
1348 | goto fail_out; | ||
1349 | } | ||
1338 | 1350 | ||
1339 | clk->name = name; | 1351 | clk->name = name; |
1340 | clk->ops = ops; | 1352 | clk->ops = ops; |
1341 | clk->hw = hw; | 1353 | clk->hw = hw; |
1342 | clk->flags = flags; | 1354 | clk->flags = flags; |
1343 | clk->parent_names = parent_names; | ||
1344 | clk->num_parents = num_parents; | 1355 | clk->num_parents = num_parents; |
1345 | hw->clk = clk; | 1356 | hw->clk = clk; |
1346 | 1357 | ||
1347 | __clk_init(dev, clk); | 1358 | /* allocate local copy in case parent_names is __initdata */ |
1359 | clk->parent_names = kzalloc((sizeof(char*) * num_parents), | ||
1360 | GFP_KERNEL); | ||
1361 | |||
1362 | if (!clk->parent_names) { | ||
1363 | pr_err("%s: could not allocate clk->parent_names\n", __func__); | ||
1364 | ret = -ENOMEM; | ||
1365 | goto fail_parent_names; | ||
1366 | } | ||
1367 | |||
1368 | |||
1369 | /* copy each string name in case parent_names is __initdata */ | ||
1370 | for (i = 0; i < num_parents; i++) { | ||
1371 | clk->parent_names[i] = kstrdup(parent_names[i], GFP_KERNEL); | ||
1372 | if (!clk->parent_names[i]) { | ||
1373 | pr_err("%s: could not copy parent_names\n", __func__); | ||
1374 | ret = -ENOMEM; | ||
1375 | goto fail_parent_names_copy; | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | ret = __clk_init(dev, clk); | ||
1380 | if (!ret) | ||
1381 | return clk; | ||
1348 | 1382 | ||
1349 | return clk; | 1383 | fail_parent_names_copy: |
1384 | while (--i >= 0) | ||
1385 | kfree(clk->parent_names[i]); | ||
1386 | kfree(clk->parent_names); | ||
1387 | fail_parent_names: | ||
1388 | kfree(clk); | ||
1389 | fail_out: | ||
1390 | return ERR_PTR(ret); | ||
1350 | } | 1391 | } |
1351 | EXPORT_SYMBOL_GPL(clk_register); | 1392 | EXPORT_SYMBOL_GPL(clk_register); |
1352 | 1393 | ||