aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/leo.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/leo.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/leo.c')
-rw-r--r--drivers/video/leo.c147
1 files changed, 70 insertions, 77 deletions
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index a038aa5a9e1c..45b9a5d55dec 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -525,130 +525,123 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
525 var->transp.length = 0; 525 var->transp.length = 0;
526} 526}
527 527
528struct all_info { 528static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
529 struct fb_info info; 529 struct leo_par *par)
530 struct leo_par par;
531};
532
533static void leo_unmap_regs(struct of_device *op, struct all_info *all)
534{ 530{
535 if (all->par.lc_ss0_usr) 531 if (par->lc_ss0_usr)
536 of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000); 532 of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
537 if (all->par.ld_ss0) 533 if (par->ld_ss0)
538 of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000); 534 of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
539 if (all->par.ld_ss1) 535 if (par->ld_ss1)
540 of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000); 536 of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
541 if (all->par.lx_krn) 537 if (par->lx_krn)
542 of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000); 538 of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
543 if (all->par.cursor) 539 if (par->cursor)
544 of_iounmap(&op->resource[0], 540 of_iounmap(&op->resource[0],
545 all->par.cursor, sizeof(struct leo_cursor)); 541 par->cursor, sizeof(struct leo_cursor));
546 if (all->info.screen_base) 542 if (info->screen_base)
547 of_iounmap(&op->resource[0], all->info.screen_base, 0x800000); 543 of_iounmap(&op->resource[0], info->screen_base, 0x800000);
548} 544}
549 545
550static int __devinit leo_init_one(struct of_device *op) 546static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match)
551{ 547{
552 struct device_node *dp = op->node; 548 struct device_node *dp = op->node;
553 struct all_info *all; 549 struct fb_info *info;
550 struct leo_par *par;
554 int linebytes, err; 551 int linebytes, err;
555 552
556 all = kzalloc(sizeof(*all), GFP_KERNEL); 553 info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
557 if (!all) 554
558 return -ENOMEM; 555 err = -ENOMEM;
556 if (!info)
557 goto out_err;
558 par = info->par;
559 559
560 spin_lock_init(&all->par.lock); 560 spin_lock_init(&par->lock);
561 561
562 all->par.physbase = op->resource[0].start; 562 par->physbase = op->resource[0].start;
563 all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; 563 par->which_io = op->resource[0].flags & IORESOURCE_BITS;
564 564
565 sbusfb_fill_var(&all->info.var, dp->node, 32); 565 sbusfb_fill_var(&info->var, dp->node, 32);
566 leo_fixup_var_rgb(&all->info.var); 566 leo_fixup_var_rgb(&info->var);
567 567
568 linebytes = of_getintprop_default(dp, "linebytes", 568 linebytes = of_getintprop_default(dp, "linebytes",
569 all->info.var.xres); 569 info->var.xres);
570 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); 570 par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
571 571
572 all->par.lc_ss0_usr = 572 par->lc_ss0_usr =
573 of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR, 573 of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
574 0x1000, "leolc ss0usr"); 574 0x1000, "leolc ss0usr");
575 all->par.ld_ss0 = 575 par->ld_ss0 =
576 of_ioremap(&op->resource[0], LEO_OFF_LD_SS0, 576 of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
577 0x1000, "leold ss0"); 577 0x1000, "leold ss0");
578 all->par.ld_ss1 = 578 par->ld_ss1 =
579 of_ioremap(&op->resource[0], LEO_OFF_LD_SS1, 579 of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
580 0x1000, "leold ss1"); 580 0x1000, "leold ss1");
581 all->par.lx_krn = 581 par->lx_krn =
582 of_ioremap(&op->resource[0], LEO_OFF_LX_KRN, 582 of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
583 0x1000, "leolx krn"); 583 0x1000, "leolx krn");
584 all->par.cursor = 584 par->cursor =
585 of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR, 585 of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
586 sizeof(struct leo_cursor), "leolx cursor"); 586 sizeof(struct leo_cursor), "leolx cursor");
587 all->info.screen_base = 587 info->screen_base =
588 of_ioremap(&op->resource[0], LEO_OFF_SS0, 588 of_ioremap(&op->resource[0], LEO_OFF_SS0,
589 0x800000, "leo ram"); 589 0x800000, "leo ram");
590 if (!all->par.lc_ss0_usr || 590 if (!par->lc_ss0_usr ||
591 !all->par.ld_ss0 || 591 !par->ld_ss0 ||
592 !all->par.ld_ss1 || 592 !par->ld_ss1 ||
593 !all->par.lx_krn || 593 !par->lx_krn ||
594 !all->par.cursor || 594 !par->cursor ||
595 !all->info.screen_base) { 595 !info->screen_base)
596 leo_unmap_regs(op, all); 596 goto out_unmap_regs;
597 kfree(all);
598 return -ENOMEM;
599 }
600 597
601 all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 598 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
602 all->info.fbops = &leo_ops; 599 info->fbops = &leo_ops;
603 all->info.par = &all->par;
604 600
605 leo_init_wids(&all->info); 601 leo_init_wids(info);
606 leo_init_hw(&all->info); 602 leo_init_hw(info);
607 603
608 leo_blank(0, &all->info); 604 leo_blank(0, info);
609 605
610 if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { 606 if (fb_alloc_cmap(&info->cmap, 256, 0))
611 leo_unmap_regs(op, all); 607 goto out_unmap_regs;
612 kfree(all);
613 return -ENOMEM;;
614 }
615 608
616 leo_init_fix(&all->info, dp); 609 leo_init_fix(info, dp);
617 610
618 err = register_framebuffer(&all->info); 611 err = register_framebuffer(info);
619 if (err < 0) { 612 if (err < 0)
620 fb_dealloc_cmap(&all->info.cmap); 613 goto out_dealloc_cmap;
621 leo_unmap_regs(op, all);
622 kfree(all);
623 return err;
624 }
625 614
626 dev_set_drvdata(&op->dev, all); 615 dev_set_drvdata(&op->dev, info);
627 616
628 printk("%s: leo at %lx:%lx\n", 617 printk("%s: leo at %lx:%lx\n",
629 dp->full_name, 618 dp->full_name,
630 all->par.which_io, all->par.physbase); 619 par->which_io, par->physbase);
631 620
632 return 0; 621 return 0;
633}
634 622
635static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match) 623out_dealloc_cmap:
636{ 624 fb_dealloc_cmap(&info->cmap);
637 struct of_device *op = to_of_device(&dev->dev); 625
626out_unmap_regs:
627 leo_unmap_regs(op, info, par);
628 framebuffer_release(info);
638 629
639 return leo_init_one(op); 630out_err:
631 return err;
640} 632}
641 633
642static int __devexit leo_remove(struct of_device *op) 634static int __devexit leo_remove(struct of_device *op)
643{ 635{
644 struct all_info *all = dev_get_drvdata(&op->dev); 636 struct fb_info *info = dev_get_drvdata(&op->dev);
637 struct leo_par *par = info->par;
645 638
646 unregister_framebuffer(&all->info); 639 unregister_framebuffer(info);
647 fb_dealloc_cmap(&all->info.cmap); 640 fb_dealloc_cmap(&info->cmap);
648 641
649 leo_unmap_regs(op, all); 642 leo_unmap_regs(op, info, par);
650 643
651 kfree(all); 644 framebuffer_release(info);
652 645
653 dev_set_drvdata(&op->dev, NULL); 646 dev_set_drvdata(&op->dev, NULL);
654 647