diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2013-10-29 15:51:04 -0400 |
---|---|---|
committer | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2013-12-04 11:19:25 -0500 |
commit | 4eadfc38c4d6e30775d3764f9a1a3098789d2acc (patch) | |
tree | a84b8471f7a311a1a5c3bfe19c116bb783ebf5ab /drivers/media | |
parent | 1d9438f7b560862fd0832355b4ad199b30e67478 (diff) |
omap3isp: Modify clocks registration to avoid circular references
The clock core code is going to be modified so clk_get() takes
reference on the clock provider module. Until the potential circular
reference issue is properly addressed, we pass NULL as the first
argument to clk_register(), in order to disallow sub-devices taking
a reference on the ISP module back trough clk_get(). This should
prevent locking the modules in memory.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/omap3isp/isp.c | 22 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isp.h | 1 |
2 files changed, 17 insertions, 6 deletions
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1c3608039663..59106623e71e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c | |||
@@ -290,9 +290,11 @@ static int isp_xclk_init(struct isp_device *isp) | |||
290 | struct clk_init_data init; | 290 | struct clk_init_data init; |
291 | unsigned int i; | 291 | unsigned int i; |
292 | 292 | ||
293 | for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) | ||
294 | isp->xclks[i].clk = ERR_PTR(-EINVAL); | ||
295 | |||
293 | for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { | 296 | for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { |
294 | struct isp_xclk *xclk = &isp->xclks[i]; | 297 | struct isp_xclk *xclk = &isp->xclks[i]; |
295 | struct clk *clk; | ||
296 | 298 | ||
297 | xclk->isp = isp; | 299 | xclk->isp = isp; |
298 | xclk->id = i == 0 ? ISP_XCLK_A : ISP_XCLK_B; | 300 | xclk->id = i == 0 ? ISP_XCLK_A : ISP_XCLK_B; |
@@ -305,10 +307,15 @@ static int isp_xclk_init(struct isp_device *isp) | |||
305 | init.num_parents = 1; | 307 | init.num_parents = 1; |
306 | 308 | ||
307 | xclk->hw.init = &init; | 309 | xclk->hw.init = &init; |
308 | 310 | /* | |
309 | clk = devm_clk_register(isp->dev, &xclk->hw); | 311 | * The first argument is NULL in order to avoid circular |
310 | if (IS_ERR(clk)) | 312 | * reference, as this driver takes reference on the |
311 | return PTR_ERR(clk); | 313 | * sensor subdevice modules and the sensors would take |
314 | * reference on this module through clk_get(). | ||
315 | */ | ||
316 | xclk->clk = clk_register(NULL, &xclk->hw); | ||
317 | if (IS_ERR(xclk->clk)) | ||
318 | return PTR_ERR(xclk->clk); | ||
312 | 319 | ||
313 | if (pdata->xclks[i].con_id == NULL && | 320 | if (pdata->xclks[i].con_id == NULL && |
314 | pdata->xclks[i].dev_id == NULL) | 321 | pdata->xclks[i].dev_id == NULL) |
@@ -320,7 +327,7 @@ static int isp_xclk_init(struct isp_device *isp) | |||
320 | 327 | ||
321 | xclk->lookup->con_id = pdata->xclks[i].con_id; | 328 | xclk->lookup->con_id = pdata->xclks[i].con_id; |
322 | xclk->lookup->dev_id = pdata->xclks[i].dev_id; | 329 | xclk->lookup->dev_id = pdata->xclks[i].dev_id; |
323 | xclk->lookup->clk = clk; | 330 | xclk->lookup->clk = xclk->clk; |
324 | 331 | ||
325 | clkdev_add(xclk->lookup); | 332 | clkdev_add(xclk->lookup); |
326 | } | 333 | } |
@@ -335,6 +342,9 @@ static void isp_xclk_cleanup(struct isp_device *isp) | |||
335 | for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { | 342 | for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { |
336 | struct isp_xclk *xclk = &isp->xclks[i]; | 343 | struct isp_xclk *xclk = &isp->xclks[i]; |
337 | 344 | ||
345 | if (!IS_ERR(xclk->clk)) | ||
346 | clk_unregister(xclk->clk); | ||
347 | |||
338 | if (xclk->lookup) | 348 | if (xclk->lookup) |
339 | clkdev_drop(xclk->lookup); | 349 | clkdev_drop(xclk->lookup); |
340 | } | 350 | } |
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index ce65d3ae1aa7..d1e857e41731 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h | |||
@@ -135,6 +135,7 @@ struct isp_xclk { | |||
135 | struct isp_device *isp; | 135 | struct isp_device *isp; |
136 | struct clk_hw hw; | 136 | struct clk_hw hw; |
137 | struct clk_lookup *lookup; | 137 | struct clk_lookup *lookup; |
138 | struct clk *clk; | ||
138 | enum isp_xclk_id id; | 139 | enum isp_xclk_id id; |
139 | 140 | ||
140 | spinlock_t lock; /* Protects enabled and divider */ | 141 | spinlock_t lock; /* Protects enabled and divider */ |