aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cg3.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-28 01:31:46 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-30 03:27:33 -0400
commitc7f439b99efbea74c70a5531f92566db5a6731f2 (patch)
tree7053ceffa23d54670862e14d0bc2eec9d5d42427 /drivers/video/cg3.c
parenta0afaa6ab12cf696d170c22a8fdfd88c3e33555c (diff)
[VIDEO]: Fix OOPS in all SBUS framebuffer drivers.
All of these drivers use a silly: struct all_info { struct fb_info info; struct foo_par par; }; struct all_info *all = kzalloc(sizeof(*all), GFP_KERNEL); all->info.par = &all->par; etc. etc. code sequence, basically replicating the provided framebuffer_alloc()/framebuffer_release(), and doing it badly. Not only is this massive code duplication, it also caused a bug in that we weren't setting the fb_info->device pointer which results in an OOPS when fb_is_primary_device() runs. Fix all of this by using framebuffer_{alloc,release}() and passing in "&of_device->dev" as the device pointer. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/video/cg3.c')
-rw-r--r--drivers/video/cg3.c136
1 files changed, 67 insertions, 69 deletions
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index f042428a84f..5741b46ade1 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -353,104 +353,102 @@ static void __devinit cg3_do_default_mode(struct cg3_par *par)
353 } 353 }
354} 354}
355 355
356struct all_info { 356static int __devinit cg3_probe(struct of_device *op,
357 struct fb_info info; 357 const struct of_device_id *match)
358 struct cg3_par par;
359};
360
361static int __devinit cg3_init_one(struct of_device *op)
362{ 358{
363 struct device_node *dp = op->node; 359 struct device_node *dp = op->node;
364 struct all_info *all; 360 struct fb_info *info;
361 struct cg3_par *par;
365 int linebytes, err; 362 int linebytes, err;
366 363
367 all = kzalloc(sizeof(*all), GFP_KERNEL); 364 info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev);
368 if (!all)
369 return -ENOMEM;
370 365
371 spin_lock_init(&all->par.lock); 366 err = -ENOMEM;
367 if (!info)
368 goto out_err;
369 par = info->par;
372 370
373 all->par.physbase = op->resource[0].start; 371 spin_lock_init(&par->lock);
374 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
375 372
376 sbusfb_fill_var(&all->info.var, dp->node, 8); 373 par->physbase = op->resource[0].start;
377 all->info.var.red.length = 8; 374 par->which_io = op->resource[0].flags & IORESOURCE_BITS;
378 all->info.var.green.length = 8; 375
379 all->info.var.blue.length = 8; 376 sbusfb_fill_var(&info->var, dp->node, 8);
377 info->var.red.length = 8;
378 info->var.green.length = 8;
379 info->var.blue.length = 8;
380 if (!strcmp(dp->name, "cgRDI")) 380 if (!strcmp(dp->name, "cgRDI"))
381 all->par.flags |= CG3_FLAG_RDI; 381 par->flags |= CG3_FLAG_RDI;
382 if (all->par.flags & CG3_FLAG_RDI) 382 if (par->flags & CG3_FLAG_RDI)
383 cg3_rdi_maybe_fixup_var(&all->info.var, dp); 383 cg3_rdi_maybe_fixup_var(&info->var, dp);
384 384
385 linebytes = of_getintprop_default(dp, "linebytes", 385 linebytes = of_getintprop_default(dp, "linebytes",
386 all->info.var.xres); 386 info->var.xres);
387 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 387 par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
388 388
389 all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET, 389 par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
390 sizeof(struct cg3_regs), "cg3 regs"); 390 sizeof(struct cg3_regs), "cg3 regs");
391 if (!par->regs)
392 goto out_release_fb;
391 393
392 all->info.flags = FBINFO_DEFAULT; 394 info->flags = FBINFO_DEFAULT;
393 all->info.fbops = &cg3_ops; 395 info->fbops = &cg3_ops;
394 all->info.screen_base = 396 info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
395 of_ioremap(&op->resource[0], CG3_RAM_OFFSET, 397 par->fbsize, "cg3 ram");
396 all->par.fbsize, "cg3 ram"); 398 if (!info->screen_base)
397 all->info.par = &all->par; 399 goto out_unmap_regs;
398 400
399 cg3_blank(0, &all->info); 401 cg3_blank(0, info);
400 402
401 if (!of_find_property(dp, "width", NULL)) 403 if (!of_find_property(dp, "width", NULL))
402 cg3_do_default_mode(&all->par); 404 cg3_do_default_mode(par);
403 405
404 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 406 if (fb_alloc_cmap(&info->cmap, 256, 0))
405 of_iounmap(&op->resource[0], 407 goto out_unmap_screen;
406 all->par.regs, sizeof(struct cg3_regs)); 408
407 of_iounmap(&op->resource[0], 409 fb_set_cmap(&info->cmap, info);
408 all->info.screen_base, all->par.fbsize);
409 kfree(all);
410 return -ENOMEM;
411 }
412 fb_set_cmap(&all->info.cmap, &all->info);
413
414 cg3_init_fix(&all->info, linebytes, dp);
415
416 err = register_framebuffer(&all->info);
417 if (err < 0) {
418 fb_dealloc_cmap(&all->info.cmap);
419 of_iounmap(&op->resource[0],
420 all->par.regs, sizeof(struct cg3_regs));
421 of_iounmap(&op->resource[0],
422 all->info.screen_base, all->par.fbsize);
423 kfree(all);
424 return err;
425 }
426 410
427 dev_set_drvdata(&op->dev, all); 411 cg3_init_fix(info, linebytes, dp);
412
413 err = register_framebuffer(info);
414 if (err < 0)
415 goto out_dealloc_cmap;
416
417 dev_set_drvdata(&op->dev, info);
428 418
429 printk("%s: cg3 at %lx:%lx\n", 419 printk("%s: cg3 at %lx:%lx\n",
430 dp->full_name, all->par.which_io, all->par.physbase); 420 dp->full_name, par->which_io, par->physbase);
431 421
432 return 0; 422 return 0;
433}
434 423
435static int __devinit cg3_probe(struct of_device *dev, 424out_dealloc_cmap:
436 const struct of_device_id *match) 425 fb_dealloc_cmap(&info->cmap);
437{ 426
438 struct of_device *op = to_of_device(&dev->dev); 427out_unmap_screen:
428 of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
429
430out_unmap_regs:
431 of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
432
433out_release_fb:
434 framebuffer_release(info);
439 435
440 return cg3_init_one(op); 436out_err:
437 return err;
441} 438}
442 439
443static int __devexit cg3_remove(struct of_device *op) 440static int __devexit cg3_remove(struct of_device *op)
444{ 441{
445 struct all_info *all = dev_get_drvdata(&op->dev); 442 struct fb_info *info = dev_get_drvdata(&op->dev);
443 struct cg3_par *par = info->par;
446 444
447 unregister_framebuffer(&all->info); 445 unregister_framebuffer(info);
448 fb_dealloc_cmap(&all->info.cmap); 446 fb_dealloc_cmap(&info->cmap);
449 447
450 of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs)); 448 of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
451 of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); 449 of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
452 450
453 kfree(all); 451 framebuffer_release(info);
454 452
455 dev_set_drvdata(&op->dev, NULL); 453 dev_set_drvdata(&op->dev, NULL);
456 454