aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/video/udlfb.c163
-rw-r--r--include/video/udlfb.h1
3 files changed, 105 insertions, 68 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 9a648eb8e213..e662b8a3e3cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2231,6 +2231,15 @@ F: Documentation/filesystems/quota.txt
2231F: fs/quota/ 2231F: fs/quota/
2232F: include/linux/quota*.h 2232F: include/linux/quota*.h
2233 2233
2234DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB)
2235M: Bernie Thompson <bernie@plugable.com>
2236L: linux-fbdev@vger.kernel.org
2237S: Maintained
2238W: http://plugable.com/category/projects/udlfb/
2239F: drivers/video/udlfb.c
2240F: include/video/udlfb.h
2241F: Documentation/fb/udlfb.txt
2242
2234DISTRIBUTED LOCK MANAGER (DLM) 2243DISTRIBUTED LOCK MANAGER (DLM)
2235M: Christine Caulfield <ccaulfie@redhat.com> 2244M: Christine Caulfield <ccaulfie@redhat.com>
2236M: David Teigland <teigland@redhat.com> 2245M: David Teigland <teigland@redhat.com>
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index a40c05ebbdc2..86c8b256e306 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
72static bool console = 1; /* Allow fbcon to open framebuffer */ 72static bool console = 1; /* Allow fbcon to open framebuffer */
73static bool fb_defio = 1; /* Detect mmap writes using page faults */ 73static bool fb_defio = 1; /* Detect mmap writes using page faults */
74static bool shadow = 1; /* Optionally disable shadow framebuffer */ 74static bool shadow = 1; /* Optionally disable shadow framebuffer */
75static int pixel_limit; /* Optionally force a pixel resolution limit */
75 76
76/* dlfb keeps a list of urbs for efficient bulk transfers */ 77/* dlfb keeps a list of urbs for efficient bulk transfers */
77static void dlfb_urb_completion(struct urb *urb); 78static void dlfb_urb_completion(struct urb *urb);
@@ -918,10 +919,6 @@ static void dlfb_free(struct kref *kref)
918{ 919{
919 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref); 920 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
920 921
921 /* this function will wait for all in-flight urbs to complete */
922 if (dev->urbs.count > 0)
923 dlfb_free_urb_list(dev);
924
925 if (dev->backing_buffer) 922 if (dev->backing_buffer)
926 vfree(dev->backing_buffer); 923 vfree(dev->backing_buffer);
927 924
@@ -940,35 +937,42 @@ static void dlfb_release_urb_work(struct work_struct *work)
940 up(&unode->dev->urbs.limit_sem); 937 up(&unode->dev->urbs.limit_sem);
941} 938}
942 939
943static void dlfb_free_framebuffer_work(struct work_struct *work) 940static void dlfb_free_framebuffer(struct dlfb_data *dev)
944{ 941{
945 struct dlfb_data *dev = container_of(work, struct dlfb_data,
946 free_framebuffer_work.work);
947 struct fb_info *info = dev->info; 942 struct fb_info *info = dev->info;
948 int node = info->node;
949 943
950 unregister_framebuffer(info); 944 if (info) {
945 int node = info->node;
951 946
952 if (info->cmap.len != 0) 947 unregister_framebuffer(info);
953 fb_dealloc_cmap(&info->cmap);
954 if (info->monspecs.modedb)
955 fb_destroy_modedb(info->monspecs.modedb);
956 if (info->screen_base)
957 vfree(info->screen_base);
958 948
959 fb_destroy_modelist(&info->modelist); 949 if (info->cmap.len != 0)
950 fb_dealloc_cmap(&info->cmap);
951 if (info->monspecs.modedb)
952 fb_destroy_modedb(info->monspecs.modedb);
953 if (info->screen_base)
954 vfree(info->screen_base);
960 955
961 dev->info = 0; 956 fb_destroy_modelist(&info->modelist);
962 957
963 /* Assume info structure is freed after this point */ 958 dev->info = NULL;
964 framebuffer_release(info);
965 959
966 pr_warn("fb_info for /dev/fb%d has been freed\n", node); 960 /* Assume info structure is freed after this point */
961 framebuffer_release(info);
962
963 pr_warn("fb_info for /dev/fb%d has been freed\n", node);
964 }
967 965
968 /* ref taken in probe() as part of registering framebfufer */ 966 /* ref taken in probe() as part of registering framebfufer */
969 kref_put(&dev->kref, dlfb_free); 967 kref_put(&dev->kref, dlfb_free);
970} 968}
971 969
970static void dlfb_free_framebuffer_work(struct work_struct *work)
971{
972 struct dlfb_data *dev = container_of(work, struct dlfb_data,
973 free_framebuffer_work.work);
974 dlfb_free_framebuffer(dev);
975}
972/* 976/*
973 * Assumes caller is holding info->lock mutex (for open and release at least) 977 * Assumes caller is holding info->lock mutex (for open and release at least)
974 */ 978 */
@@ -1012,7 +1016,8 @@ static int dlfb_is_valid_mode(struct fb_videomode *mode,
1012 return 0; 1016 return 0;
1013 } 1017 }
1014 1018
1015 pr_info("%dx%d valid mode\n", mode->xres, mode->yres); 1019 pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres,
1020 mode->refresh);
1016 1021
1017 return 1; 1022 return 1;
1018} 1023}
@@ -1537,7 +1542,7 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1537 u8 length; 1542 u8 length;
1538 u16 key; 1543 u16 key;
1539 1544
1540 key = *((u16 *) desc); 1545 key = le16_to_cpu(*((u16 *) desc));
1541 desc += sizeof(u16); 1546 desc += sizeof(u16);
1542 length = *desc; 1547 length = *desc;
1543 desc++; 1548 desc++;
@@ -1570,14 +1575,15 @@ success:
1570 kfree(buf); 1575 kfree(buf);
1571 return true; 1576 return true;
1572} 1577}
1578
1579static void dlfb_init_framebuffer_work(struct work_struct *work);
1580
1573static int dlfb_usb_probe(struct usb_interface *interface, 1581static int dlfb_usb_probe(struct usb_interface *interface,
1574 const struct usb_device_id *id) 1582 const struct usb_device_id *id)
1575{ 1583{
1576 struct usb_device *usbdev; 1584 struct usb_device *usbdev;
1577 struct dlfb_data *dev = 0; 1585 struct dlfb_data *dev = 0;
1578 struct fb_info *info = 0;
1579 int retval = -ENOMEM; 1586 int retval = -ENOMEM;
1580 int i;
1581 1587
1582 /* usb initialization */ 1588 /* usb initialization */
1583 1589
@@ -1589,9 +1595,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1589 goto error; 1595 goto error;
1590 } 1596 }
1591 1597
1592 /* we need to wait for both usb and fbdev to spin down on disconnect */
1593 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ 1598 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
1594 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1595 1599
1596 dev->udev = usbdev; 1600 dev->udev = usbdev;
1597 dev->gdev = &usbdev->dev; /* our generic struct device * */ 1601 dev->gdev = &usbdev->dev; /* our generic struct device * */
@@ -1613,16 +1617,53 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1613 goto error; 1617 goto error;
1614 } 1618 }
1615 1619
1620 if (pixel_limit) {
1621 pr_warn("DL chip limit of %d overriden"
1622 " by module param to %d\n",
1623 dev->sku_pixel_limit, pixel_limit);
1624 dev->sku_pixel_limit = pixel_limit;
1625 }
1626
1627
1616 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { 1628 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
1617 retval = -ENOMEM; 1629 retval = -ENOMEM;
1618 pr_err("dlfb_alloc_urb_list failed\n"); 1630 pr_err("dlfb_alloc_urb_list failed\n");
1619 goto error; 1631 goto error;
1620 } 1632 }
1621 1633
1634 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1635
1622 /* We don't register a new USB class. Our client interface is fbdev */ 1636 /* We don't register a new USB class. Our client interface is fbdev */
1623 1637
1638 /* Workitem keep things fast & simple during USB enumeration */
1639 INIT_DELAYED_WORK(&dev->init_framebuffer_work,
1640 dlfb_init_framebuffer_work);
1641 schedule_delayed_work(&dev->init_framebuffer_work, 0);
1642
1643 return 0;
1644
1645error:
1646 if (dev) {
1647
1648 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1649 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1650
1651 /* dev has been deallocated. Do not dereference */
1652 }
1653
1654 return retval;
1655}
1656
1657static void dlfb_init_framebuffer_work(struct work_struct *work)
1658{
1659 struct dlfb_data *dev = container_of(work, struct dlfb_data,
1660 init_framebuffer_work.work);
1661 struct fb_info *info;
1662 int retval;
1663 int i;
1664
1624 /* allocates framebuffer driver structure, not framebuffer memory */ 1665 /* allocates framebuffer driver structure, not framebuffer memory */
1625 info = framebuffer_alloc(0, &interface->dev); 1666 info = framebuffer_alloc(0, dev->gdev);
1626 if (!info) { 1667 if (!info) {
1627 retval = -ENOMEM; 1668 retval = -ENOMEM;
1628 pr_err("framebuffer_alloc failed\n"); 1669 pr_err("framebuffer_alloc failed\n");
@@ -1668,15 +1709,13 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1668 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { 1709 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
1669 retval = device_create_file(info->dev, &fb_device_attrs[i]); 1710 retval = device_create_file(info->dev, &fb_device_attrs[i]);
1670 if (retval) { 1711 if (retval) {
1671 pr_err("device_create_file failed %d\n", retval); 1712 pr_warn("device_create_file failed %d\n", retval);
1672 goto err_del_attrs;
1673 } 1713 }
1674 } 1714 }
1675 1715
1676 retval = device_create_bin_file(info->dev, &edid_attr); 1716 retval = device_create_bin_file(info->dev, &edid_attr);
1677 if (retval) { 1717 if (retval) {
1678 pr_err("device_create_bin_file failed %d\n", retval); 1718 pr_warn("device_create_bin_file failed %d\n", retval);
1679 goto err_del_attrs;
1680 } 1719 }
1681 1720
1682 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." 1721 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
@@ -1684,38 +1723,10 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1684 info->var.xres, info->var.yres, 1723 info->var.xres, info->var.yres,
1685 ((dev->backing_buffer) ? 1724 ((dev->backing_buffer) ?
1686 info->fix.smem_len * 2 : info->fix.smem_len) >> 10); 1725 info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
1687 return 0; 1726 return;
1688
1689err_del_attrs:
1690 for (i -= 1; i >= 0; i--)
1691 device_remove_file(info->dev, &fb_device_attrs[i]);
1692 1727
1693error: 1728error:
1694 if (dev) { 1729 dlfb_free_framebuffer(dev);
1695
1696 if (info) {
1697 if (info->cmap.len != 0)
1698 fb_dealloc_cmap(&info->cmap);
1699 if (info->monspecs.modedb)
1700 fb_destroy_modedb(info->monspecs.modedb);
1701 if (info->screen_base)
1702 vfree(info->screen_base);
1703
1704 fb_destroy_modelist(&info->modelist);
1705
1706 framebuffer_release(info);
1707 }
1708
1709 if (dev->backing_buffer)
1710 vfree(dev->backing_buffer);
1711
1712 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1713 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1714
1715 /* dev has been deallocated. Do not dereference */
1716 }
1717
1718 return retval;
1719} 1730}
1720 1731
1721static void dlfb_usb_disconnect(struct usb_interface *interface) 1732static void dlfb_usb_disconnect(struct usb_interface *interface)
@@ -1735,12 +1746,24 @@ static void dlfb_usb_disconnect(struct usb_interface *interface)
1735 /* When non-active we'll update virtual framebuffer, but no new urbs */ 1746 /* When non-active we'll update virtual framebuffer, but no new urbs */
1736 atomic_set(&dev->usb_active, 0); 1747 atomic_set(&dev->usb_active, 0);
1737 1748
1738 /* remove udlfb's sysfs interfaces */ 1749 /* this function will wait for all in-flight urbs to complete */
1739 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) 1750 dlfb_free_urb_list(dev);
1740 device_remove_file(info->dev, &fb_device_attrs[i]); 1751
1741 device_remove_bin_file(info->dev, &edid_attr); 1752 if (info) {
1742 unlink_framebuffer(info); 1753
1754 /* remove udlfb's sysfs interfaces */
1755 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
1756 device_remove_file(info->dev, &fb_device_attrs[i]);
1757 device_remove_bin_file(info->dev, &edid_attr);
1758
1759 /* it's safe to uncomment next line if your kernel
1760 doesn't yet have this function exported */
1761 unlink_framebuffer(info);
1762 }
1763
1743 usb_set_intfdata(interface, NULL); 1764 usb_set_intfdata(interface, NULL);
1765 dev->udev = NULL;
1766 dev->gdev = NULL;
1744 1767
1745 /* if clients still have us open, will be freed on last close */ 1768 /* if clients still have us open, will be freed on last close */
1746 if (dev->fb_count == 0) 1769 if (dev->fb_count == 0)
@@ -1806,12 +1829,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1806 int ret; 1829 int ret;
1807 unsigned long flags; 1830 unsigned long flags;
1808 1831
1809 pr_notice("Waiting for completes and freeing all render urbs\n"); 1832 pr_notice("Freeing all render urbs\n");
1810 1833
1811 /* keep waiting and freeing, until we've got 'em all */ 1834 /* keep waiting and freeing, until we've got 'em all */
1812 while (count--) { 1835 while (count--) {
1813 1836
1814 /* Getting interrupted means a leak, but ok at shutdown*/ 1837 /* Getting interrupted means a leak, but ok at disconnect */
1815 ret = down_interruptible(&dev->urbs.limit_sem); 1838 ret = down_interruptible(&dev->urbs.limit_sem);
1816 if (ret) 1839 if (ret)
1817 break; 1840 break;
@@ -1833,6 +1856,7 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1833 kfree(node); 1856 kfree(node);
1834 } 1857 }
1835 1858
1859 dev->urbs.count = 0;
1836} 1860}
1837 1861
1838static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) 1862static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
@@ -1948,6 +1972,9 @@ MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
1948module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 1972module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1949MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); 1973MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
1950 1974
1975module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1976MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)");
1977
1951MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " 1978MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1952 "Jaya Kumar <jayakumar.lkml@gmail.com>, " 1979 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
1953 "Bernie Thompson <bernie@plugable.com>"); 1980 "Bernie Thompson <bernie@plugable.com>");
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
index c41f308c9636..f9466fa54ba4 100644
--- a/include/video/udlfb.h
+++ b/include/video/udlfb.h
@@ -41,6 +41,7 @@ struct dlfb_data {
41 char *backing_buffer; 41 char *backing_buffer;
42 int fb_count; 42 int fb_count;
43 bool virtualized; /* true when physical usb device not present */ 43 bool virtualized; /* true when physical usb device not present */
44 struct delayed_work init_framebuffer_work;
44 struct delayed_work free_framebuffer_work; 45 struct delayed_work free_framebuffer_work;
45 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 46 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
46 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ 47 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */