diff options
| author | Bruno Prémont <bonbons@linux-vserver.org> | 2009-01-04 16:11:54 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-04 16:33:20 -0500 |
| commit | e687d691cb3790d25e31c74f5941fd7c565e9df5 (patch) | |
| tree | d606511c734e99fb6e4786d20ab42a8cf1b2232f | |
| parent | c644f0e4b56f9a2fc066cd0d75a18074d130e4a3 (diff) | |
viafb: fix crashes due to 4k stack overflow
The function viafb_cursor() uses 2 stack-variables of CURSOR_SIZE bits;
CURSOR_SIZE is defined as (8 * 1024). Using up twice 1k on stack is too
much for 4k-stack (though it works with 8k-stacks). Make those two
variables kzalloc'ed to preserve stack space.
Also merge the whole lot of local struct's in viafb_ioctl into a union so
the stack usage gets minimized here as well. (struct's are only accessed
in their indicidual IOCTL case) This second part is only compile-tested as
I know of no userspace app using the IOCTLs.
Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
Cc: <JosephChan@via.com.tw>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/video/via/viafbdev.c | 248 |
1 files changed, 129 insertions, 119 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 73ac754ad801..e21fe5b6f9ff 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
| @@ -546,23 +546,25 @@ static int viafb_blank(int blank_mode, struct fb_info *info) | |||
| 546 | 546 | ||
| 547 | static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | 547 | static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 548 | { | 548 | { |
| 549 | struct viafb_ioctl_mode viamode; | 549 | union { |
| 550 | struct viafb_ioctl_samm viasamm; | 550 | struct viafb_ioctl_mode viamode; |
| 551 | struct viafb_driver_version driver_version; | 551 | struct viafb_ioctl_samm viasamm; |
| 552 | struct fb_var_screeninfo sec_var; | 552 | struct viafb_driver_version driver_version; |
| 553 | struct _panel_size_pos_info panel_pos_size_para; | 553 | struct fb_var_screeninfo sec_var; |
| 554 | struct _panel_size_pos_info panel_pos_size_para; | ||
| 555 | struct viafb_ioctl_setting viafb_setting; | ||
| 556 | struct device_t active_dev; | ||
| 557 | } u; | ||
| 554 | u32 state_info = 0; | 558 | u32 state_info = 0; |
| 555 | u32 viainfo_size = sizeof(struct viafb_ioctl_info); | ||
| 556 | u32 *viafb_gamma_table; | 559 | u32 *viafb_gamma_table; |
| 557 | char driver_name[] = "viafb"; | 560 | char driver_name[] = "viafb"; |
| 558 | 561 | ||
| 559 | u32 __user *argp = (u32 __user *) arg; | 562 | u32 __user *argp = (u32 __user *) arg; |
| 560 | u32 gpu32; | 563 | u32 gpu32; |
| 561 | u32 video_dev_info = 0; | 564 | u32 video_dev_info = 0; |
| 562 | struct viafb_ioctl_setting viafb_setting = {}; | ||
| 563 | struct device_t active_dev = {}; | ||
| 564 | 565 | ||
| 565 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); | 566 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); |
| 567 | memset(&u, 0, sizeof(u)); | ||
| 566 | 568 | ||
| 567 | switch (cmd) { | 569 | switch (cmd) { |
| 568 | case VIAFB_GET_CHIP_INFO: | 570 | case VIAFB_GET_CHIP_INFO: |
| @@ -571,7 +573,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
| 571 | return -EFAULT; | 573 | return -EFAULT; |
| 572 | break; | 574 | break; |
| 573 | case VIAFB_GET_INFO_SIZE: | 575 | case VIAFB_GET_INFO_SIZE: |
| 574 | return put_user(viainfo_size, argp); | 576 | return put_user((u32)sizeof(struct viafb_ioctl_info), argp); |
| 575 | case VIAFB_GET_INFO: | 577 | case VIAFB_GET_INFO: |
| 576 | return viafb_ioctl_get_viafb_info(arg); | 578 | return viafb_ioctl_get_viafb_info(arg); |
| 577 | case VIAFB_HOTPLUG: | 579 | case VIAFB_HOTPLUG: |
| @@ -584,60 +586,60 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
| 584 | viafb_hotplug = (gpu32) ? 1 : 0; | 586 | viafb_hotplug = (gpu32) ? 1 : 0; |
| 585 | break; | 587 | break; |
| 586 | case VIAFB_GET_RESOLUTION: | 588 | case VIAFB_GET_RESOLUTION: |
| 587 | viamode.xres = (u32) viafb_hotplug_Xres; | 589 | u.viamode.xres = (u32) viafb_hotplug_Xres; |
| 588 | viamode.yres = (u32) viafb_hotplug_Yres; | 590 | u.viamode.yres = (u32) viafb_hotplug_Yres; |
| 589 | viamode.refresh = (u32) viafb_hotplug_refresh; | 591 | u.viamode.refresh = (u32) viafb_hotplug_refresh; |
| 590 | viamode.bpp = (u32) viafb_hotplug_bpp; | 592 | u.viamode.bpp = (u32) viafb_hotplug_bpp; |
| 591 | if (viafb_SAMM_ON == 1) { | 593 | if (viafb_SAMM_ON == 1) { |
| 592 | viamode.xres_sec = viafb_second_xres; | 594 | u.viamode.xres_sec = viafb_second_xres; |
| 593 | viamode.yres_sec = viafb_second_yres; | 595 | u.viamode.yres_sec = viafb_second_yres; |
| 594 | viamode.virtual_xres_sec = viafb_second_virtual_xres; | 596 | u.viamode.virtual_xres_sec = viafb_second_virtual_xres; |
| 595 | viamode.virtual_yres_sec = viafb_second_virtual_yres; | 597 | u.viamode.virtual_yres_sec = viafb_second_virtual_yres; |
| 596 | viamode.refresh_sec = viafb_refresh1; | 598 | u.viamode.refresh_sec = viafb_refresh1; |
| 597 | viamode.bpp_sec = viafb_bpp1; | 599 | u.viamode.bpp_sec = viafb_bpp1; |
| 598 | } else { | 600 | } else { |
| 599 | viamode.xres_sec = 0; | 601 | u.viamode.xres_sec = 0; |
| 600 | viamode.yres_sec = 0; | 602 | u.viamode.yres_sec = 0; |
| 601 | viamode.virtual_xres_sec = 0; | 603 | u.viamode.virtual_xres_sec = 0; |
| 602 | viamode.virtual_yres_sec = 0; | 604 | u.viamode.virtual_yres_sec = 0; |
| 603 | viamode.refresh_sec = 0; | 605 | u.viamode.refresh_sec = 0; |
| 604 | viamode.bpp_sec = 0; | 606 | u.viamode.bpp_sec = 0; |
| 605 | } | 607 | } |
| 606 | if (copy_to_user(argp, &viamode, sizeof(viamode))) | 608 | if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) |
| 607 | return -EFAULT; | 609 | return -EFAULT; |
| 608 | break; | 610 | break; |
| 609 | case VIAFB_GET_SAMM_INFO: | 611 | case VIAFB_GET_SAMM_INFO: |
| 610 | viasamm.samm_status = viafb_SAMM_ON; | 612 | u.viasamm.samm_status = viafb_SAMM_ON; |
| 611 | 613 | ||
| 612 | if (viafb_SAMM_ON == 1) { | 614 | if (viafb_SAMM_ON == 1) { |
| 613 | if (viafb_dual_fb) { | 615 | if (viafb_dual_fb) { |
| 614 | viasamm.size_prim = viaparinfo->fbmem_free; | 616 | u.viasamm.size_prim = viaparinfo->fbmem_free; |
| 615 | viasamm.size_sec = viaparinfo1->fbmem_free; | 617 | u.viasamm.size_sec = viaparinfo1->fbmem_free; |
| 616 | } else { | 618 | } else { |
| 617 | if (viafb_second_size) { | 619 | if (viafb_second_size) { |
| 618 | viasamm.size_prim = | 620 | u.viasamm.size_prim = |
| 619 | viaparinfo->fbmem_free - | 621 | viaparinfo->fbmem_free - |
| 620 | viafb_second_size * 1024 * 1024; | 622 | viafb_second_size * 1024 * 1024; |
| 621 | viasamm.size_sec = | 623 | u.viasamm.size_sec = |
| 622 | viafb_second_size * 1024 * 1024; | 624 | viafb_second_size * 1024 * 1024; |
| 623 | } else { | 625 | } else { |
| 624 | viasamm.size_prim = | 626 | u.viasamm.size_prim = |
| 625 | viaparinfo->fbmem_free >> 1; | 627 | viaparinfo->fbmem_free >> 1; |
| 626 | viasamm.size_sec = | 628 | u.viasamm.size_sec = |
| 627 | (viaparinfo->fbmem_free >> 1); | 629 | (viaparinfo->fbmem_free >> 1); |
| 628 | } | 630 | } |
| 629 | } | 631 | } |
| 630 | viasamm.mem_base = viaparinfo->fbmem; | 632 | u.viasamm.mem_base = viaparinfo->fbmem; |
| 631 | viasamm.offset_sec = viafb_second_offset; | 633 | u.viasamm.offset_sec = viafb_second_offset; |
| 632 | } else { | 634 | } else { |
| 633 | viasamm.size_prim = | 635 | u.viasamm.size_prim = |
| 634 | viaparinfo->memsize - viaparinfo->fbmem_used; | 636 | viaparinfo->memsize - viaparinfo->fbmem_used; |
| 635 | viasamm.size_sec = 0; | 637 | u.viasamm.size_sec = 0; |
| 636 | viasamm.mem_base = viaparinfo->fbmem; | 638 | u.viasamm.mem_base = viaparinfo->fbmem; |
| 637 | viasamm.offset_sec = 0; | 639 | u.viasamm.offset_sec = 0; |
| 638 | } | 640 | } |
| 639 | 641 | ||
| 640 | if (copy_to_user(argp, &viasamm, sizeof(viasamm))) | 642 | if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) |
| 641 | return -EFAULT; | 643 | return -EFAULT; |
| 642 | 644 | ||
| 643 | break; | 645 | break; |
| @@ -662,74 +664,75 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
| 662 | viafb_lcd_disable(); | 664 | viafb_lcd_disable(); |
| 663 | break; | 665 | break; |
| 664 | case VIAFB_SET_DEVICE: | 666 | case VIAFB_SET_DEVICE: |
| 665 | if (copy_from_user(&active_dev, (void *)argp, | 667 | if (copy_from_user(&u.active_dev, (void *)argp, |
| 666 | sizeof(active_dev))) | 668 | sizeof(u.active_dev))) |
| 667 | return -EFAULT; | 669 | return -EFAULT; |
| 668 | viafb_set_device(active_dev); | 670 | viafb_set_device(u.active_dev); |
| 669 | viafb_set_par(info); | 671 | viafb_set_par(info); |
| 670 | break; | 672 | break; |
| 671 | case VIAFB_GET_DEVICE: | 673 | case VIAFB_GET_DEVICE: |
| 672 | active_dev.crt = viafb_CRT_ON; | 674 | u.active_dev.crt = viafb_CRT_ON; |
| 673 | active_dev.dvi = viafb_DVI_ON; | 675 | u.active_dev.dvi = viafb_DVI_ON; |
| 674 | active_dev.lcd = viafb_LCD_ON; | 676 | u.active_dev.lcd = viafb_LCD_ON; |
| 675 | active_dev.samm = viafb_SAMM_ON; | 677 | u.active_dev.samm = viafb_SAMM_ON; |
| 676 | active_dev.primary_dev = viafb_primary_dev; | 678 | u.active_dev.primary_dev = viafb_primary_dev; |
| 677 | 679 | ||
| 678 | active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; | 680 | u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; |
| 679 | active_dev.lcd_panel_id = viafb_lcd_panel_id; | 681 | u.active_dev.lcd_panel_id = viafb_lcd_panel_id; |
| 680 | active_dev.lcd_mode = viafb_lcd_mode; | 682 | u.active_dev.lcd_mode = viafb_lcd_mode; |
| 681 | 683 | ||
| 682 | active_dev.xres = viafb_hotplug_Xres; | 684 | u.active_dev.xres = viafb_hotplug_Xres; |
| 683 | active_dev.yres = viafb_hotplug_Yres; | 685 | u.active_dev.yres = viafb_hotplug_Yres; |
| 684 | 686 | ||
| 685 | active_dev.xres1 = viafb_second_xres; | 687 | u.active_dev.xres1 = viafb_second_xres; |
| 686 | active_dev.yres1 = viafb_second_yres; | 688 | u.active_dev.yres1 = viafb_second_yres; |
| 687 | 689 | ||
| 688 | active_dev.bpp = viafb_bpp; | 690 | u.active_dev.bpp = viafb_bpp; |
| 689 | active_dev.bpp1 = viafb_bpp1; | 691 | u.active_dev.bpp1 = viafb_bpp1; |
| 690 | active_dev.refresh = viafb_refresh; | 692 | u.active_dev.refresh = viafb_refresh; |
| 691 | active_dev.refresh1 = viafb_refresh1; | 693 | u.active_dev.refresh1 = viafb_refresh1; |
| 692 | 694 | ||
| 693 | active_dev.epia_dvi = viafb_platform_epia_dvi; | 695 | u.active_dev.epia_dvi = viafb_platform_epia_dvi; |
| 694 | active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; | 696 | u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; |
| 695 | active_dev.bus_width = viafb_bus_width; | 697 | u.active_dev.bus_width = viafb_bus_width; |
| 696 | 698 | ||
| 697 | if (copy_to_user(argp, &active_dev, sizeof(active_dev))) | 699 | if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev))) |
| 698 | return -EFAULT; | 700 | return -EFAULT; |
| 699 | break; | 701 | break; |
| 700 | 702 | ||
| 701 | case VIAFB_GET_DRIVER_VERSION: | 703 | case VIAFB_GET_DRIVER_VERSION: |
| 702 | driver_version.iMajorNum = VERSION_MAJOR; | 704 | u.driver_version.iMajorNum = VERSION_MAJOR; |
| 703 | driver_version.iKernelNum = VERSION_KERNEL; | 705 | u.driver_version.iKernelNum = VERSION_KERNEL; |
| 704 | driver_version.iOSNum = VERSION_OS; | 706 | u.driver_version.iOSNum = VERSION_OS; |
| 705 | driver_version.iMinorNum = VERSION_MINOR; | 707 | u.driver_version.iMinorNum = VERSION_MINOR; |
| 706 | 708 | ||
| 707 | if (copy_to_user(argp, &driver_version, | 709 | if (copy_to_user(argp, &u.driver_version, |
| 708 | sizeof(driver_version))) | 710 | sizeof(u.driver_version))) |
| 709 | return -EFAULT; | 711 | return -EFAULT; |
| 710 | 712 | ||
| 711 | break; | 713 | break; |
| 712 | 714 | ||
| 713 | case VIAFB_SET_DEVICE_INFO: | 715 | case VIAFB_SET_DEVICE_INFO: |
| 714 | if (copy_from_user(&viafb_setting, | 716 | if (copy_from_user(&u.viafb_setting, |
| 715 | argp, sizeof(viafb_setting))) | 717 | argp, sizeof(u.viafb_setting))) |
| 716 | return -EFAULT; | 718 | return -EFAULT; |
| 717 | if (apply_device_setting(viafb_setting, info) < 0) | 719 | if (apply_device_setting(u.viafb_setting, info) < 0) |
| 718 | return -EINVAL; | 720 | return -EINVAL; |
| 719 | 721 | ||
| 720 | break; | 722 | break; |
| 721 | 723 | ||
| 722 | case VIAFB_SET_SECOND_MODE: | 724 | case VIAFB_SET_SECOND_MODE: |
| 723 | if (copy_from_user(&sec_var, argp, sizeof(sec_var))) | 725 | if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var))) |
| 724 | return -EFAULT; | 726 | return -EFAULT; |
| 725 | apply_second_mode_setting(&sec_var); | 727 | apply_second_mode_setting(&u.sec_var); |
| 726 | break; | 728 | break; |
| 727 | 729 | ||
| 728 | case VIAFB_GET_DEVICE_INFO: | 730 | case VIAFB_GET_DEVICE_INFO: |
| 729 | 731 | ||
| 730 | retrieve_device_setting(&viafb_setting); | 732 | retrieve_device_setting(&u.viafb_setting); |
| 731 | 733 | ||
| 732 | if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting))) | 734 | if (copy_to_user(argp, &u.viafb_setting, |
| 735 | sizeof(u.viafb_setting))) | ||
| 733 | return -EFAULT; | 736 | return -EFAULT; |
| 734 | 737 | ||
| 735 | break; | 738 | break; |
| @@ -806,51 +809,51 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
| 806 | break; | 809 | break; |
| 807 | 810 | ||
| 808 | case VIAFB_GET_PANEL_MAX_SIZE: | 811 | case VIAFB_GET_PANEL_MAX_SIZE: |
| 809 | if (copy_from_user | 812 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 810 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 813 | sizeof(u.panel_pos_size_para))) |
| 811 | return -EFAULT; | 814 | return -EFAULT; |
| 812 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 815 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
| 813 | if (copy_to_user(argp, &panel_pos_size_para, | 816 | if (copy_to_user(argp, &u.panel_pos_size_para, |
| 814 | sizeof(panel_pos_size_para))) | 817 | sizeof(u.panel_pos_size_para))) |
| 815 | return -EFAULT; | 818 | return -EFAULT; |
| 816 | break; | 819 | break; |
| 817 | case VIAFB_GET_PANEL_MAX_POSITION: | 820 | case VIAFB_GET_PANEL_MAX_POSITION: |
| 818 | if (copy_from_user | 821 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 819 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 822 | sizeof(u.panel_pos_size_para))) |
| 820 | return -EFAULT; | 823 | return -EFAULT; |
| 821 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 824 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
| 822 | if (copy_to_user(argp, &panel_pos_size_para, | 825 | if (copy_to_user(argp, &u.panel_pos_size_para, |
| 823 | sizeof(panel_pos_size_para))) | 826 | sizeof(u.panel_pos_size_para))) |
| 824 | return -EFAULT; | 827 | return -EFAULT; |
| 825 | break; | 828 | break; |
| 826 | 829 | ||
| 827 | case VIAFB_GET_PANEL_POSITION: | 830 | case VIAFB_GET_PANEL_POSITION: |
| 828 | if (copy_from_user | 831 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 829 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 832 | sizeof(u.panel_pos_size_para))) |
| 830 | return -EFAULT; | 833 | return -EFAULT; |
| 831 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 834 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
| 832 | if (copy_to_user(argp, &panel_pos_size_para, | 835 | if (copy_to_user(argp, &u.panel_pos_size_para, |
| 833 | sizeof(panel_pos_size_para))) | 836 | sizeof(u.panel_pos_size_para))) |
| 834 | return -EFAULT; | 837 | return -EFAULT; |
| 835 | break; | 838 | break; |
| 836 | case VIAFB_GET_PANEL_SIZE: | 839 | case VIAFB_GET_PANEL_SIZE: |
| 837 | if (copy_from_user | 840 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 838 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 841 | sizeof(u.panel_pos_size_para))) |
| 839 | return -EFAULT; | 842 | return -EFAULT; |
| 840 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 843 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
| 841 | if (copy_to_user(argp, &panel_pos_size_para, | 844 | if (copy_to_user(argp, &u.panel_pos_size_para, |
| 842 | sizeof(panel_pos_size_para))) | 845 | sizeof(u.panel_pos_size_para))) |
| 843 | return -EFAULT; | 846 | return -EFAULT; |
| 844 | break; | 847 | break; |
| 845 | 848 | ||
| 846 | case VIAFB_SET_PANEL_POSITION: | 849 | case VIAFB_SET_PANEL_POSITION: |
| 847 | if (copy_from_user | 850 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 848 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 851 | sizeof(u.panel_pos_size_para))) |
| 849 | return -EFAULT; | 852 | return -EFAULT; |
| 850 | break; | 853 | break; |
| 851 | case VIAFB_SET_PANEL_SIZE: | 854 | case VIAFB_SET_PANEL_SIZE: |
| 852 | if (copy_from_user | 855 | if (copy_from_user(&u.panel_pos_size_para, argp, |
| 853 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 856 | sizeof(u.panel_pos_size_para))) |
| 854 | return -EFAULT; | 857 | return -EFAULT; |
| 855 | break; | 858 | break; |
| 856 | 859 | ||
| @@ -1052,10 +1055,8 @@ static void viafb_imageblit(struct fb_info *info, | |||
| 1052 | 1055 | ||
| 1053 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 1056 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
| 1054 | { | 1057 | { |
| 1055 | u8 data[CURSOR_SIZE / 8]; | ||
| 1056 | u32 data_bak[CURSOR_SIZE / 32]; | ||
| 1057 | u32 temp, xx, yy, bg_col = 0, fg_col = 0; | 1058 | u32 temp, xx, yy, bg_col = 0, fg_col = 0; |
| 1058 | int size, i, j = 0; | 1059 | int i, j = 0; |
| 1059 | static int hw_cursor; | 1060 | static int hw_cursor; |
| 1060 | struct viafb_par *p_viafb_par; | 1061 | struct viafb_par *p_viafb_par; |
| 1061 | 1062 | ||
| @@ -1178,22 +1179,29 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 1178 | } | 1179 | } |
| 1179 | 1180 | ||
| 1180 | if (cursor->set & FB_CUR_SETSHAPE) { | 1181 | if (cursor->set & FB_CUR_SETSHAPE) { |
| 1181 | size = | 1182 | struct { |
| 1183 | u8 data[CURSOR_SIZE / 8]; | ||
| 1184 | u32 bak[CURSOR_SIZE / 32]; | ||
| 1185 | } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); | ||
| 1186 | int size = | ||
| 1182 | ((viacursor.image.width + 7) >> 3) * | 1187 | ((viacursor.image.width + 7) >> 3) * |
| 1183 | viacursor.image.height; | 1188 | viacursor.image.height; |
| 1184 | 1189 | ||
| 1190 | if (cr_data == NULL) | ||
| 1191 | goto out; | ||
| 1192 | |||
| 1185 | if (MAX_CURS == 32) { | 1193 | if (MAX_CURS == 32) { |
| 1186 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | 1194 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { |
| 1187 | data_bak[i] = 0x0; | 1195 | cr_data->bak[i] = 0x0; |
| 1188 | data_bak[i + 1] = 0xFFFFFFFF; | 1196 | cr_data->bak[i + 1] = 0xFFFFFFFF; |
| 1189 | i += 1; | 1197 | i += 1; |
| 1190 | } | 1198 | } |
| 1191 | } else if (MAX_CURS == 64) { | 1199 | } else if (MAX_CURS == 64) { |
| 1192 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | 1200 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { |
| 1193 | data_bak[i] = 0x0; | 1201 | cr_data->bak[i] = 0x0; |
| 1194 | data_bak[i + 1] = 0x0; | 1202 | cr_data->bak[i + 1] = 0x0; |
| 1195 | data_bak[i + 2] = 0xFFFFFFFF; | 1203 | cr_data->bak[i + 2] = 0xFFFFFFFF; |
| 1196 | data_bak[i + 3] = 0xFFFFFFFF; | 1204 | cr_data->bak[i + 3] = 0xFFFFFFFF; |
| 1197 | i += 3; | 1205 | i += 3; |
| 1198 | } | 1206 | } |
| 1199 | } | 1207 | } |
| @@ -1201,12 +1209,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 1201 | switch (viacursor.rop) { | 1209 | switch (viacursor.rop) { |
| 1202 | case ROP_XOR: | 1210 | case ROP_XOR: |
| 1203 | for (i = 0; i < size; i++) | 1211 | for (i = 0; i < size; i++) |
| 1204 | data[i] = viacursor.mask[i]; | 1212 | cr_data->data[i] = viacursor.mask[i]; |
| 1205 | break; | 1213 | break; |
| 1206 | case ROP_COPY: | 1214 | case ROP_COPY: |
| 1207 | 1215 | ||
| 1208 | for (i = 0; i < size; i++) | 1216 | for (i = 0; i < size; i++) |
| 1209 | data[i] = viacursor.mask[i]; | 1217 | cr_data->data[i] = viacursor.mask[i]; |
| 1210 | break; | 1218 | break; |
| 1211 | default: | 1219 | default: |
| 1212 | break; | 1220 | break; |
| @@ -1214,23 +1222,25 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 1214 | 1222 | ||
| 1215 | if (MAX_CURS == 32) { | 1223 | if (MAX_CURS == 32) { |
| 1216 | for (i = 0; i < size; i++) { | 1224 | for (i = 0; i < size; i++) { |
| 1217 | data_bak[j] = (u32) data[i]; | 1225 | cr_data->bak[j] = (u32) cr_data->data[i]; |
| 1218 | data_bak[j + 1] = ~data_bak[j]; | 1226 | cr_data->bak[j + 1] = ~cr_data->bak[j]; |
| 1219 | j += 2; | 1227 | j += 2; |
| 1220 | } | 1228 | } |
| 1221 | } else if (MAX_CURS == 64) { | 1229 | } else if (MAX_CURS == 64) { |
| 1222 | for (i = 0; i < size; i++) { | 1230 | for (i = 0; i < size; i++) { |
| 1223 | data_bak[j] = (u32) data[i]; | 1231 | cr_data->bak[j] = (u32) cr_data->data[i]; |
| 1224 | data_bak[j + 1] = 0x0; | 1232 | cr_data->bak[j + 1] = 0x0; |
| 1225 | data_bak[j + 2] = ~data_bak[j]; | 1233 | cr_data->bak[j + 2] = ~cr_data->bak[j]; |
| 1226 | data_bak[j + 3] = ~data_bak[j + 1]; | 1234 | cr_data->bak[j + 3] = ~cr_data->bak[j + 1]; |
| 1227 | j += 4; | 1235 | j += 4; |
| 1228 | } | 1236 | } |
| 1229 | } | 1237 | } |
| 1230 | 1238 | ||
| 1231 | memcpy(((struct viafb_par *)(info->par))->fbmem_virt + | 1239 | memcpy(((struct viafb_par *)(info->par))->fbmem_virt + |
| 1232 | ((struct viafb_par *)(info->par))->cursor_start, | 1240 | ((struct viafb_par *)(info->par))->cursor_start, |
| 1233 | data_bak, CURSOR_SIZE); | 1241 | cr_data->bak, CURSOR_SIZE); |
| 1242 | out: | ||
| 1243 | kfree(cr_data); | ||
| 1234 | } | 1244 | } |
| 1235 | 1245 | ||
| 1236 | if (viacursor.enable) | 1246 | if (viacursor.enable) |
