aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-14 14:24:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-14 14:24:32 -0400
commitafa49791caae70cc3fd665a182eea61250795265 (patch)
tree5a1683ad60a9c789802cfb2ac657981a6e43410e
parent22fe9446e82f1fe4b59900db4599061384efb0ad (diff)
parentc590cece75728a85ea06801df3ebad2d7ad8612c (diff)
Merge branch 'fbmem'
* fbmem: Further fbcon sanity checking fbmem: fix remove_conflicting_framebuffers races
-rw-r--r--drivers/video/fbmem.c123
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
1540static int do_unregister_framebuffer(struct fb_info *fb_info);
1541
1540#define VGA_FB_PHYS 0xA0000 1542#define VGA_FB_PHYS 0xA0000
1541void remove_conflicting_framebuffers(struct apertures_struct *a, 1543static 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}
1567EXPORT_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
1579int 1570static int do_register_framebuffer(struct fb_info *fb_info)
1580register_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(&registration_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(&registration_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 1636static 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
1666int
1667unregister_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(&registration_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);
1704done: 1667 return 0;
1668}
1669
1670void remove_conflicting_framebuffers(struct apertures_struct *a,
1671 const char *name, bool primary)
1672{
1673 mutex_lock(&registration_lock);
1674 do_remove_conflicting_framebuffers(a, name, primary);
1675 mutex_unlock(&registration_lock);
1676}
1677EXPORT_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 */
1688int
1689register_framebuffer(struct fb_info *fb_info)
1690{
1691 int ret;
1692
1693 mutex_lock(&registration_lock);
1694 ret = do_register_framebuffer(fb_info);
1695 mutex_unlock(&registration_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 */
1716int
1717unregister_framebuffer(struct fb_info *fb_info)
1718{
1719 int ret;
1720
1721 mutex_lock(&registration_lock);
1722 ret = do_unregister_framebuffer(fb_info);
1705 mutex_unlock(&registration_lock); 1723 mutex_unlock(&registration_lock);
1724
1706 return ret; 1725 return ret;
1707} 1726}
1708 1727