diff options
| -rw-r--r-- | drivers/video/fbmem.c | 123 |
1 files changed, 71 insertions, 52 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index ea16e654a9b6..5aac00eb1830 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -1537,8 +1537,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, | |||
| 1537 | return false; | 1537 | return false; |
| 1538 | } | 1538 | } |
| 1539 | 1539 | ||
| 1540 | static int do_unregister_framebuffer(struct fb_info *fb_info); | ||
| 1541 | |||
| 1540 | #define VGA_FB_PHYS 0xA0000 | 1542 | #define VGA_FB_PHYS 0xA0000 |
| 1541 | void remove_conflicting_framebuffers(struct apertures_struct *a, | 1543 | static void do_remove_conflicting_framebuffers(struct apertures_struct *a, |
| 1542 | const char *name, bool primary) | 1544 | const char *name, bool primary) |
| 1543 | { | 1545 | { |
| 1544 | int i; | 1546 | int i; |
| @@ -1560,39 +1562,26 @@ void remove_conflicting_framebuffers(struct apertures_struct *a, | |||
| 1560 | printk(KERN_INFO "fb: conflicting fb hw usage " | 1562 | printk(KERN_INFO "fb: conflicting fb hw usage " |
| 1561 | "%s vs %s - removing generic driver\n", | 1563 | "%s vs %s - removing generic driver\n", |
| 1562 | name, registered_fb[i]->fix.id); | 1564 | name, registered_fb[i]->fix.id); |
| 1563 | unregister_framebuffer(registered_fb[i]); | 1565 | do_unregister_framebuffer(registered_fb[i]); |
| 1564 | } | 1566 | } |
| 1565 | } | 1567 | } |
| 1566 | } | 1568 | } |
| 1567 | EXPORT_SYMBOL(remove_conflicting_framebuffers); | ||
| 1568 | |||
| 1569 | /** | ||
| 1570 | * register_framebuffer - registers a frame buffer device | ||
| 1571 | * @fb_info: frame buffer info structure | ||
| 1572 | * | ||
| 1573 | * Registers a frame buffer device @fb_info. | ||
| 1574 | * | ||
| 1575 | * Returns negative errno on error, or zero for success. | ||
| 1576 | * | ||
| 1577 | */ | ||
| 1578 | 1569 | ||
| 1579 | int | 1570 | static int do_register_framebuffer(struct fb_info *fb_info) |
| 1580 | register_framebuffer(struct fb_info *fb_info) | ||
| 1581 | { | 1571 | { |
| 1582 | int i; | 1572 | int i; |
| 1583 | struct fb_event event; | 1573 | struct fb_event event; |
| 1584 | struct fb_videomode mode; | 1574 | struct fb_videomode mode; |
| 1585 | 1575 | ||
| 1586 | if (num_registered_fb == FB_MAX) | ||
| 1587 | return -ENXIO; | ||
| 1588 | |||
| 1589 | if (fb_check_foreignness(fb_info)) | 1576 | if (fb_check_foreignness(fb_info)) |
| 1590 | return -ENOSYS; | 1577 | return -ENOSYS; |
| 1591 | 1578 | ||
| 1592 | remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, | 1579 | do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, |
| 1593 | fb_is_primary_device(fb_info)); | 1580 | fb_is_primary_device(fb_info)); |
| 1594 | 1581 | ||
| 1595 | mutex_lock(®istration_lock); | 1582 | if (num_registered_fb == FB_MAX) |
| 1583 | return -ENXIO; | ||
| 1584 | |||
| 1596 | num_registered_fb++; | 1585 | num_registered_fb++; |
| 1597 | for (i = 0 ; i < FB_MAX; i++) | 1586 | for (i = 0 ; i < FB_MAX; i++) |
| 1598 | if (!registered_fb[i]) | 1587 | if (!registered_fb[i]) |
| @@ -1635,7 +1624,6 @@ register_framebuffer(struct fb_info *fb_info) | |||
| 1635 | fb_var_to_videomode(&mode, &fb_info->var); | 1624 | fb_var_to_videomode(&mode, &fb_info->var); |
| 1636 | fb_add_videomode(&mode, &fb_info->modelist); | 1625 | fb_add_videomode(&mode, &fb_info->modelist); |
| 1637 | registered_fb[i] = fb_info; | 1626 | registered_fb[i] = fb_info; |
| 1638 | mutex_unlock(®istration_lock); | ||
| 1639 | 1627 | ||
| 1640 | event.info = fb_info; | 1628 | event.info = fb_info; |
| 1641 | if (!lock_fb_info(fb_info)) | 1629 | if (!lock_fb_info(fb_info)) |
| @@ -1645,37 +1633,14 @@ register_framebuffer(struct fb_info *fb_info) | |||
| 1645 | return 0; | 1633 | return 0; |
| 1646 | } | 1634 | } |
| 1647 | 1635 | ||
| 1648 | 1636 | static int do_unregister_framebuffer(struct fb_info *fb_info) | |
| 1649 | /** | ||
| 1650 | * unregister_framebuffer - releases a frame buffer device | ||
| 1651 | * @fb_info: frame buffer info structure | ||
| 1652 | * | ||
| 1653 | * Unregisters a frame buffer device @fb_info. | ||
| 1654 | * | ||
| 1655 | * Returns negative errno on error, or zero for success. | ||
| 1656 | * | ||
| 1657 | * This function will also notify the framebuffer console | ||
| 1658 | * to release the driver. | ||
| 1659 | * | ||
| 1660 | * This is meant to be called within a driver's module_exit() | ||
| 1661 | * function. If this is called outside module_exit(), ensure | ||
| 1662 | * that the driver implements fb_open() and fb_release() to | ||
| 1663 | * check that no processes are using the device. | ||
| 1664 | */ | ||
| 1665 | |||
| 1666 | int | ||
| 1667 | unregister_framebuffer(struct fb_info *fb_info) | ||
| 1668 | { | 1637 | { |
| 1669 | struct fb_event event; | 1638 | struct fb_event event; |
| 1670 | int i, ret = 0; | 1639 | int i, ret = 0; |
| 1671 | 1640 | ||
| 1672 | mutex_lock(®istration_lock); | ||
| 1673 | i = fb_info->node; | 1641 | i = fb_info->node; |
| 1674 | if (!registered_fb[i]) { | 1642 | if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) |
| 1675 | ret = -EINVAL; | 1643 | return -EINVAL; |
| 1676 | goto done; | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | 1644 | ||
| 1680 | if (!lock_fb_info(fb_info)) | 1645 | if (!lock_fb_info(fb_info)) |
| 1681 | return -ENODEV; | 1646 | return -ENODEV; |
| @@ -1683,10 +1648,8 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
| 1683 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); | 1648 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); |
| 1684 | unlock_fb_info(fb_info); | 1649 | unlock_fb_info(fb_info); |
| 1685 | 1650 | ||
| 1686 | if (ret) { | 1651 | if (ret) |
| 1687 | ret = -EINVAL; | 1652 | return -EINVAL; |
| 1688 | goto done; | ||
| 1689 | } | ||
| 1690 | 1653 | ||
| 1691 | if (fb_info->pixmap.addr && | 1654 | if (fb_info->pixmap.addr && |
| 1692 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) | 1655 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) |
| @@ -1701,8 +1664,64 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
| 1701 | 1664 | ||
| 1702 | /* this may free fb info */ | 1665 | /* this may free fb info */ |
| 1703 | put_fb_info(fb_info); | 1666 | put_fb_info(fb_info); |
| 1704 | done: | 1667 | return 0; |
| 1668 | } | ||
| 1669 | |||
| 1670 | void remove_conflicting_framebuffers(struct apertures_struct *a, | ||
| 1671 | const char *name, bool primary) | ||
| 1672 | { | ||
| 1673 | mutex_lock(®istration_lock); | ||
| 1674 | do_remove_conflicting_framebuffers(a, name, primary); | ||
| 1675 | mutex_unlock(®istration_lock); | ||
| 1676 | } | ||
| 1677 | EXPORT_SYMBOL(remove_conflicting_framebuffers); | ||
| 1678 | |||
| 1679 | /** | ||
| 1680 | * register_framebuffer - registers a frame buffer device | ||
| 1681 | * @fb_info: frame buffer info structure | ||
| 1682 | * | ||
| 1683 | * Registers a frame buffer device @fb_info. | ||
| 1684 | * | ||
| 1685 | * Returns negative errno on error, or zero for success. | ||
| 1686 | * | ||
| 1687 | */ | ||
| 1688 | int | ||
| 1689 | register_framebuffer(struct fb_info *fb_info) | ||
| 1690 | { | ||
| 1691 | int ret; | ||
| 1692 | |||
| 1693 | mutex_lock(®istration_lock); | ||
| 1694 | ret = do_register_framebuffer(fb_info); | ||
| 1695 | mutex_unlock(®istration_lock); | ||
| 1696 | |||
| 1697 | return ret; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | /** | ||
| 1701 | * unregister_framebuffer - releases a frame buffer device | ||
| 1702 | * @fb_info: frame buffer info structure | ||
| 1703 | * | ||
| 1704 | * Unregisters a frame buffer device @fb_info. | ||
| 1705 | * | ||
| 1706 | * Returns negative errno on error, or zero for success. | ||
| 1707 | * | ||
| 1708 | * This function will also notify the framebuffer console | ||
| 1709 | * to release the driver. | ||
| 1710 | * | ||
| 1711 | * This is meant to be called within a driver's module_exit() | ||
| 1712 | * function. If this is called outside module_exit(), ensure | ||
| 1713 | * that the driver implements fb_open() and fb_release() to | ||
| 1714 | * check that no processes are using the device. | ||
| 1715 | */ | ||
| 1716 | int | ||
| 1717 | unregister_framebuffer(struct fb_info *fb_info) | ||
| 1718 | { | ||
| 1719 | int ret; | ||
| 1720 | |||
| 1721 | mutex_lock(®istration_lock); | ||
| 1722 | ret = do_unregister_framebuffer(fb_info); | ||
| 1705 | mutex_unlock(®istration_lock); | 1723 | mutex_unlock(®istration_lock); |
| 1724 | |||
| 1706 | return ret; | 1725 | return ret; |
| 1707 | } | 1726 | } |
| 1708 | 1727 | ||
