aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulia Lawall <Julia.Lawall@lip6.fr>2013-04-02 14:20:36 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-04 06:07:34 -0400
commit9e340fdc5af6ae3041d73319bbd1438c7d6d566c (patch)
treeb6a3495de254294a65fa1decf510365d6e727f43
parent3d20837dd6bd2891d5788c0a574edaf2b54fc377 (diff)
drivers/video/wm8505fb.c: use devm_ functions
The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. The patch makes some other cleanups. First, the original code used devm_kzalloc, but kfree. This would lead to a double free. The problem was found using the following semantic match (http://coccinelle.lip6.fr/): // <smpl> @@ expression x,e; @@ x = devm_kzalloc(...) ... when != x = e ?-kfree(x,...); // </smpl> The error-handing code of devm_request_and_ioremap does not print any warning message, because devm_request_and_ioremap does this. The call to dma_alloc_coherent is converted to its devm equivalent, dmam_alloc_coherent. This implicitly introduces a call to dmam_free_coherent, which was completly missing in the original code. A semicolon is removed at the end of the error-handling code for the call to dma_alloc_coherent. The block of code calling fb_alloc_cmap is moved below the block of code calling wm8505fb_set_par, so that the error-handing code of the call to wm8505fb_set_par can just return ret. This way there is only one block of error-handling code that needs to call fb_dealloc_cmap, and so this is moved up to the place where it is needed, eliminating the need for all gotos and labels in the function. This was suggested by Tony Prisk. The initializations of fbi and ret at the beginning of the function are not necessary and are removed. The call platform_set_drvdata(pdev, NULL); at the end of the function is also removed. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Tony Prisk <linux@prisktech.co.nz> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/wm8505fb.c79
1 files changed, 19 insertions, 60 deletions
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index fe9afd60a018..020df1ddb674 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -272,15 +272,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
272 unsigned long fb_mem_len; 272 unsigned long fb_mem_len;
273 void *fb_mem_virt; 273 void *fb_mem_virt;
274 274
275 ret = -ENOMEM;
276 fbi = NULL;
277
278 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + 275 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
279 sizeof(u32) * 16, GFP_KERNEL); 276 sizeof(u32) * 16, GFP_KERNEL);
280 if (!fbi) { 277 if (!fbi) {
281 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); 278 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
282 ret = -ENOMEM; 279 return -ENOMEM;
283 goto failed;
284 } 280 }
285 281
286 strcpy(fbi->fb.fix.id, DRIVER_NAME); 282 strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -306,31 +302,14 @@ static int wm8505fb_probe(struct platform_device *pdev)
306 fbi->fb.pseudo_palette = addr; 302 fbi->fb.pseudo_palette = addr;
307 303
308 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 304 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
309 if (res == NULL) { 305 fbi->regbase = devm_request_and_ioremap(&pdev->dev, res);
310 dev_err(&pdev->dev, "no I/O memory resource defined\n"); 306 if (fbi->regbase == NULL)
311 ret = -ENODEV; 307 return -EBUSY;
312 goto failed_fbi;
313 }
314
315 res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
316 if (res == NULL) {
317 dev_err(&pdev->dev, "failed to request I/O memory\n");
318 ret = -EBUSY;
319 goto failed_fbi;
320 }
321
322 fbi->regbase = ioremap(res->start, resource_size(res));
323 if (fbi->regbase == NULL) {
324 dev_err(&pdev->dev, "failed to map I/O memory\n");
325 ret = -EBUSY;
326 goto failed_free_res;
327 }
328 308
329 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0); 309 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
330 if (!np) { 310 if (!np) {
331 pr_err("%s: No display description in Device Tree\n", __func__); 311 pr_err("%s: No display description in Device Tree\n", __func__);
332 ret = -EINVAL; 312 return -EINVAL;
333 goto failed_free_res;
334 } 313 }
335 314
336 /* 315 /*
@@ -349,7 +328,7 @@ static int wm8505fb_probe(struct platform_device *pdev)
349 ret |= of_property_read_u32(np, "bpp", &bpp); 328 ret |= of_property_read_u32(np, "bpp", &bpp);
350 if (ret) { 329 if (ret) {
351 pr_err("%s: Unable to read display properties\n", __func__); 330 pr_err("%s: Unable to read display properties\n", __func__);
352 goto failed_free_res; 331 return -EINVAL;
353 } 332 }
354 333
355 of_mode.vmode = FB_VMODE_NONINTERLACED; 334 of_mode.vmode = FB_VMODE_NONINTERLACED;
@@ -363,12 +342,12 @@ static int wm8505fb_probe(struct platform_device *pdev)
363 342
364 /* try allocating the framebuffer */ 343 /* try allocating the framebuffer */
365 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); 344 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
366 fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, 345 fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
367 GFP_KERNEL); 346 GFP_KERNEL);
368 if (!fb_mem_virt) { 347 if (!fb_mem_virt) {
369 pr_err("%s: Failed to allocate framebuffer\n", __func__); 348 pr_err("%s: Failed to allocate framebuffer\n", __func__);
370 return -ENOMEM; 349 return -ENOMEM;
371 }; 350 }
372 351
373 fbi->fb.var.xres_virtual = of_mode.xres; 352 fbi->fb.var.xres_virtual = of_mode.xres;
374 fbi->fb.var.yres_virtual = of_mode.yres * 2; 353 fbi->fb.var.yres_virtual = of_mode.yres * 2;
@@ -379,28 +358,29 @@ static int wm8505fb_probe(struct platform_device *pdev)
379 fbi->fb.screen_base = fb_mem_virt; 358 fbi->fb.screen_base = fb_mem_virt;
380 fbi->fb.screen_size = fb_mem_len; 359 fbi->fb.screen_size = fb_mem_len;
381 360
382 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
383 dev_err(&pdev->dev, "Failed to allocate color map\n");
384 ret = -ENOMEM;
385 goto failed_free_io;
386 }
387
388 wm8505fb_init_hw(&fbi->fb);
389
390 fbi->contrast = 0x80; 361 fbi->contrast = 0x80;
391 ret = wm8505fb_set_par(&fbi->fb); 362 ret = wm8505fb_set_par(&fbi->fb);
392 if (ret) { 363 if (ret) {
393 dev_err(&pdev->dev, "Failed to set parameters\n"); 364 dev_err(&pdev->dev, "Failed to set parameters\n");
394 goto failed_free_cmap; 365 return ret;
395 } 366 }
396 367
368 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
369 dev_err(&pdev->dev, "Failed to allocate color map\n");
370 return -ENOMEM;
371 }
372
373 wm8505fb_init_hw(&fbi->fb);
374
397 platform_set_drvdata(pdev, fbi); 375 platform_set_drvdata(pdev, fbi);
398 376
399 ret = register_framebuffer(&fbi->fb); 377 ret = register_framebuffer(&fbi->fb);
400 if (ret < 0) { 378 if (ret < 0) {
401 dev_err(&pdev->dev, 379 dev_err(&pdev->dev,
402 "Failed to register framebuffer device: %d\n", ret); 380 "Failed to register framebuffer device: %d\n", ret);
403 goto failed_free_cmap; 381 if (fbi->fb.cmap.len)
382 fb_dealloc_cmap(&fbi->fb.cmap);
383 return ret;
404 } 384 }
405 385
406 ret = device_create_file(&pdev->dev, &dev_attr_contrast); 386 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -414,25 +394,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
414 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); 394 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
415 395
416 return 0; 396 return 0;
417
418failed_free_cmap:
419 if (fbi->fb.cmap.len)
420 fb_dealloc_cmap(&fbi->fb.cmap);
421failed_free_io:
422 iounmap(fbi->regbase);
423failed_free_res:
424 release_mem_region(res->start, resource_size(res));
425failed_fbi:
426 platform_set_drvdata(pdev, NULL);
427 kfree(fbi);
428failed:
429 return ret;
430} 397}
431 398
432static int wm8505fb_remove(struct platform_device *pdev) 399static int wm8505fb_remove(struct platform_device *pdev)
433{ 400{
434 struct wm8505fb_info *fbi = platform_get_drvdata(pdev); 401 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
435 struct resource *res;
436 402
437 device_remove_file(&pdev->dev, &dev_attr_contrast); 403 device_remove_file(&pdev->dev, &dev_attr_contrast);
438 404
@@ -443,13 +409,6 @@ static int wm8505fb_remove(struct platform_device *pdev)
443 if (fbi->fb.cmap.len) 409 if (fbi->fb.cmap.len)
444 fb_dealloc_cmap(&fbi->fb.cmap); 410 fb_dealloc_cmap(&fbi->fb.cmap);
445 411
446 iounmap(fbi->regbase);
447
448 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
449 release_mem_region(res->start, resource_size(res));
450
451 kfree(fbi);
452
453 return 0; 412 return 0;
454} 413}
455 414