Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'fbmem'

* fbmem:
Further fbcon sanity checking
fbmem: fix remove_conflicting_framebuffers races

+75 -56
+75 -56
drivers/video/fbmem.c
··· 1537 1537 return false; 1538 1538 } 1539 1539 1540 + static int do_unregister_framebuffer(struct fb_info *fb_info); 1541 + 1540 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 1544 const char *name, bool primary) 1543 1545 { 1544 1546 int i; ··· 1562 1560 printk(KERN_INFO "fb: conflicting fb hw usage " 1563 1561 "%s vs %s - removing generic driver\n", 1564 1562 name, registered_fb[i]->fix.id); 1565 - unregister_framebuffer(registered_fb[i]); 1563 + do_unregister_framebuffer(registered_fb[i]); 1566 1564 } 1567 1565 } 1568 1566 } 1569 - EXPORT_SYMBOL(remove_conflicting_framebuffers); 1570 1567 1571 - /** 1572 - * register_framebuffer - registers a frame buffer device 1573 - * @fb_info: frame buffer info structure 1574 - * 1575 - * Registers a frame buffer device @fb_info. 1576 - * 1577 - * Returns negative errno on error, or zero for success. 1578 - * 1579 - */ 1580 - 1581 - int 1582 - register_framebuffer(struct fb_info *fb_info) 1568 + static int do_register_framebuffer(struct fb_info *fb_info) 1583 1569 { 1584 1570 int i; 1585 1571 struct fb_event event; 1586 1572 struct fb_videomode mode; 1587 1573 1588 - if (num_registered_fb == FB_MAX) 1589 - return -ENXIO; 1590 - 1591 1574 if (fb_check_foreignness(fb_info)) 1592 1575 return -ENOSYS; 1593 1576 1594 - remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, 1577 + do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, 1595 1578 fb_is_primary_device(fb_info)); 1596 1579 1597 - mutex_lock(&registration_lock); 1580 + if (num_registered_fb == FB_MAX) 1581 + return -ENXIO; 1582 + 1598 1583 num_registered_fb++; 1599 1584 for (i = 0 ; i < FB_MAX; i++) 1600 1585 if (!registered_fb[i]) ··· 1624 1635 fb_var_to_videomode(&mode, &fb_info->var); 1625 1636 fb_add_videomode(&mode, &fb_info->modelist); 1626 1637 registered_fb[i] = fb_info; 1627 - mutex_unlock(&registration_lock); 1628 1638 1629 1639 event.info = fb_info; 1630 1640 if (!lock_fb_info(fb_info)) ··· 1633 1645 return 0; 1634 1646 } 1635 1647 1648 + static int do_unregister_framebuffer(struct fb_info *fb_info) 1649 + { 1650 + struct fb_event event; 1651 + int i, ret = 0; 1652 + 1653 + i = fb_info->node; 1654 + if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) 1655 + return -EINVAL; 1656 + 1657 + if (!lock_fb_info(fb_info)) 1658 + return -ENODEV; 1659 + event.info = fb_info; 1660 + ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); 1661 + unlock_fb_info(fb_info); 1662 + 1663 + if (ret) 1664 + return -EINVAL; 1665 + 1666 + if (fb_info->pixmap.addr && 1667 + (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1668 + kfree(fb_info->pixmap.addr); 1669 + fb_destroy_modelist(&fb_info->modelist); 1670 + registered_fb[i] = NULL; 1671 + num_registered_fb--; 1672 + fb_cleanup_device(fb_info); 1673 + device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1674 + event.info = fb_info; 1675 + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1676 + 1677 + /* this may free fb info */ 1678 + put_fb_info(fb_info); 1679 + return 0; 1680 + } 1681 + 1682 + void remove_conflicting_framebuffers(struct apertures_struct *a, 1683 + const char *name, bool primary) 1684 + { 1685 + mutex_lock(&registration_lock); 1686 + do_remove_conflicting_framebuffers(a, name, primary); 1687 + mutex_unlock(&registration_lock); 1688 + } 1689 + EXPORT_SYMBOL(remove_conflicting_framebuffers); 1690 + 1691 + /** 1692 + * register_framebuffer - registers a frame buffer device 1693 + * @fb_info: frame buffer info structure 1694 + * 1695 + * Registers a frame buffer device @fb_info. 1696 + * 1697 + * Returns negative errno on error, or zero for success. 1698 + * 1699 + */ 1700 + int 1701 + register_framebuffer(struct fb_info *fb_info) 1702 + { 1703 + int ret; 1704 + 1705 + mutex_lock(&registration_lock); 1706 + ret = do_register_framebuffer(fb_info); 1707 + mutex_unlock(&registration_lock); 1708 + 1709 + return ret; 1710 + } 1636 1711 1637 1712 /** 1638 1713 * unregister_framebuffer - releases a frame buffer device ··· 1713 1662 * that the driver implements fb_open() and fb_release() to 1714 1663 * check that no processes are using the device. 1715 1664 */ 1716 - 1717 1665 int 1718 1666 unregister_framebuffer(struct fb_info *fb_info) 1719 1667 { 1720 - struct fb_event event; 1721 - int i, ret = 0; 1668 + int ret; 1722 1669 1723 1670 mutex_lock(&registration_lock); 1724 - i = fb_info->node; 1725 - if (!registered_fb[i]) { 1726 - ret = -EINVAL; 1727 - goto done; 1728 - } 1729 - 1730 - 1731 - if (!lock_fb_info(fb_info)) 1732 - return -ENODEV; 1733 - event.info = fb_info; 1734 - ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); 1735 - unlock_fb_info(fb_info); 1736 - 1737 - if (ret) { 1738 - ret = -EINVAL; 1739 - goto done; 1740 - } 1741 - 1742 - if (fb_info->pixmap.addr && 1743 - (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1744 - kfree(fb_info->pixmap.addr); 1745 - fb_destroy_modelist(&fb_info->modelist); 1746 - registered_fb[i] = NULL; 1747 - num_registered_fb--; 1748 - fb_cleanup_device(fb_info); 1749 - device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1750 - event.info = fb_info; 1751 - fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1752 - 1753 - /* this may free fb info */ 1754 - put_fb_info(fb_info); 1755 - done: 1671 + ret = do_unregister_framebuffer(fb_info); 1756 1672 mutex_unlock(&registration_lock); 1673 + 1757 1674 return ret; 1758 1675 } 1759 1676