aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cg6.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/cg6.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/cg6.c')
-rw-r--r--drivers/video/cg6.c161
1 files changed, 73 insertions, 88 deletions
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 4dad23a28f58..87c747123538 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -653,135 +653,120 @@ static void cg6_chip_init(struct fb_info *info)
653 sbus_writel(info->var.yres - 1, &fbc->clipmaxy); 653 sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
654} 654}
655 655
656struct all_info { 656static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
657 struct fb_info info; 657 struct cg6_par *par)
658 struct cg6_par par;
659};
660
661static void cg6_unmap_regs(struct of_device *op, struct all_info *all)
662{ 658{
663 if (all->par.fbc) 659 if (par->fbc)
664 of_iounmap(&op->resource[0], all->par.fbc, 4096); 660 of_iounmap(&op->resource[0], par->fbc, 4096);
665 if (all->par.tec) 661 if (par->tec)
666 of_iounmap(&op->resource[0], 662 of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
667 all->par.tec, sizeof(struct cg6_tec)); 663 if (par->thc)
668 if (all->par.thc) 664 of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
669 of_iounmap(&op->resource[0], 665 if (par->bt)
670 all->par.thc, sizeof(struct cg6_thc)); 666 of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
671 if (all->par.bt) 667 if (par->fhc)
672 of_iounmap(&op->resource[0], 668 of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
673 all->par.bt, sizeof(struct bt_regs)); 669
674 if (all->par.fhc) 670 if (info->screen_base)
675 of_iounmap(&op->resource[0], 671 of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
676 all->par.fhc, sizeof(u32));
677
678 if (all->info.screen_base)
679 of_iounmap(&op->resource[0],
680 all->info.screen_base, all->par.fbsize);
681} 672}
682 673
683static int __devinit cg6_init_one(struct of_device *op) 674static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match)
684{ 675{
685 struct device_node *dp = op->node; 676 struct device_node *dp = op->node;
686 struct all_info *all; 677 struct fb_info *info;
678 struct cg6_par *par;
687 int linebytes, err; 679 int linebytes, err;
688 680
689 all = kzalloc(sizeof(*all), GFP_KERNEL); 681 info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
690 if (!all) 682
691 return -ENOMEM; 683 err = -ENOMEM;
684 if (!info)
685 goto out_err;
686 par = info->par;
692 687
693 spin_lock_init(&all->par.lock); 688 spin_lock_init(&par->lock);
694 689
695 all->par.physbase = op->resource[0].start; 690 par->physbase = op->resource[0].start;
696 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; 691 par->which_io = op->resource[0].flags & IORESOURCE_BITS;
697 692
698 sbusfb_fill_var(&all->info.var, dp->node, 8); 693 sbusfb_fill_var(&info->var, dp->node, 8);
699 all->info.var.red.length = 8; 694 info->var.red.length = 8;
700 all->info.var.green.length = 8; 695 info->var.green.length = 8;
701 all->info.var.blue.length = 8; 696 info->var.blue.length = 8;
702 697
703 linebytes = of_getintprop_default(dp, "linebytes", 698 linebytes = of_getintprop_default(dp, "linebytes",
704 all->info.var.xres); 699 info->var.xres);
705 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 700 par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
706 if (of_find_property(dp, "dblbuf", NULL)) 701 if (of_find_property(dp, "dblbuf", NULL))
707 all->par.fbsize *= 4; 702 par->fbsize *= 4;
708 703
709 all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, 704 par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
710 4096, "cgsix fbc"); 705 4096, "cgsix fbc");
711 all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, 706 par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
712 sizeof(struct cg6_tec), "cgsix tec"); 707 sizeof(struct cg6_tec), "cgsix tec");
713 all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, 708 par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
714 sizeof(struct cg6_thc), "cgsix thc"); 709 sizeof(struct cg6_thc), "cgsix thc");
715 all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, 710 par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
716 sizeof(struct bt_regs), "cgsix dac"); 711 sizeof(struct bt_regs), "cgsix dac");
717 all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, 712 par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
718 sizeof(u32), "cgsix fhc"); 713 sizeof(u32), "cgsix fhc");
719 714
720 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | 715 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
721 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; 716 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
722 all->info.fbops = &cg6_ops; 717 info->fbops = &cg6_ops;
723
724 all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
725 all->par.fbsize, "cgsix ram");
726 if (!all->par.fbc || !all->par.tec || !all->par.thc ||
727 !all->par.bt || !all->par.fhc || !all->info.screen_base) {
728 cg6_unmap_regs(op, all);
729 kfree(all);
730 return -ENOMEM;
731 }
732 718
733 all->info.par = &all->par; 719 info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
720 par->fbsize, "cgsix ram");
721 if (!par->fbc || !par->tec || !par->thc ||
722 !par->bt || !par->fhc || !info->screen_base)
723 goto out_unmap_regs;
734 724
735 all->info.var.accel_flags = FB_ACCELF_TEXT; 725 info->var.accel_flags = FB_ACCELF_TEXT;
736 726
737 cg6_bt_init(&all->par); 727 cg6_bt_init(par);
738 cg6_chip_init(&all->info); 728 cg6_chip_init(info);
739 cg6_blank(0, &all->info); 729 cg6_blank(0, info);
740 730
741 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 731 if (fb_alloc_cmap(&info->cmap, 256, 0))
742 cg6_unmap_regs(op, all); 732 goto out_unmap_regs;
743 kfree(all);
744 return -ENOMEM;
745 }
746 733
747 fb_set_cmap(&all->info.cmap, &all->info); 734 fb_set_cmap(&info->cmap, info);
748 cg6_init_fix(&all->info, linebytes); 735 cg6_init_fix(info, linebytes);
749 736
750 err = register_framebuffer(&all->info); 737 err = register_framebuffer(info);
751 if (err < 0) { 738 if (err < 0)
752 cg6_unmap_regs(op, all); 739 goto out_dealloc_cmap;
753 fb_dealloc_cmap(&all->info.cmap);
754 kfree(all);
755 return err;
756 }
757 740
758 dev_set_drvdata(&op->dev, all); 741 dev_set_drvdata(&op->dev, info);
759 742
760 printk("%s: CGsix [%s] at %lx:%lx\n", 743 printk("%s: CGsix [%s] at %lx:%lx\n",
761 dp->full_name, 744 dp->full_name, info->fix.id,
762 all->info.fix.id, 745 par->which_io, par->physbase);
763 all->par.which_io, all->par.physbase);
764 746
765 return 0; 747 return 0;
766}
767 748
768static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match) 749out_dealloc_cmap:
769{ 750 fb_dealloc_cmap(&info->cmap);
770 struct of_device *op = to_of_device(&dev->dev); 751
752out_unmap_regs:
753 cg6_unmap_regs(op, info, par);
771 754
772 return cg6_init_one(op); 755out_err:
756 return err;
773} 757}
774 758
775static int __devexit cg6_remove(struct of_device *op) 759static int __devexit cg6_remove(struct of_device *op)
776{ 760{
777 struct all_info *all = dev_get_drvdata(&op->dev); 761 struct fb_info *info = dev_get_drvdata(&op->dev);
762 struct cg6_par *par = info->par;
778 763
779 unregister_framebuffer(&all->info); 764 unregister_framebuffer(info);
780 fb_dealloc_cmap(&all->info.cmap); 765 fb_dealloc_cmap(&info->cmap);
781 766
782 cg6_unmap_regs(op, all); 767 cg6_unmap_regs(op, info, par);
783 768
784 kfree(all); 769 framebuffer_release(info);
785 770
786 dev_set_drvdata(&op->dev, NULL); 771 dev_set_drvdata(&op->dev, NULL);
787 772