aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernie Thompson <bernie@plugable.com>2010-09-05 19:35:39 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-05 19:50:22 -0400
commitd5ed54322e54d48e5fa66dff0086b79211f1cde7 (patch)
treef5566dd732a86dd97848aace06b6adb920123961
parent8ef8cc4fca4a92e77c0b5aa7a852a6c3d2fba844 (diff)
staging: udlfb: add module options for console and fb_defio
Add module options for console and fb_defio Convert fb_defio on/off switch to module option and add console option. >From the command line, pass options to modprobe modprobe udlfb defio=1 console=1 Or for permanent option, create file like /etc/modprobe.d/options with text options udlfb defio=1 console=1 Accepted options: fb_defio Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel module to track changed areas of the framebuffer by page faults. Standard fbdev applications that use mmap but that do not report damage, may be able to work with this enabled. Disabled by default because of overhead and other issues. console Allow fbcon to attach to udlfb provided framebuffers. This is disabled by default because fbcon will aggressively consume the first framebuffer it finds, which isn't usually what the user wants in the case of USB displays. Signed-off-by: Bernie Thompson <bernie@plugable.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/udlfb/udlfb.c178
-rw-r--r--drivers/staging/udlfb/udlfb.h1
2 files changed, 81 insertions, 98 deletions
diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
index b13869bbe09..80a1e0e0ab7 100644
--- a/drivers/staging/udlfb/udlfb.c
+++ b/drivers/staging/udlfb/udlfb.c
@@ -59,19 +59,9 @@ static struct usb_device_id id_table[] = {
59}; 59};
60MODULE_DEVICE_TABLE(usb, id_table); 60MODULE_DEVICE_TABLE(usb, id_table);
61 61
62#ifndef CONFIG_FB_DEFERRED_IO 62/* module options */
63#warning Please set CONFIG_FB_DEFFERRED_IO option to support generic fbdev apps 63static int console; /* Optionally allow fbcon to consume first framebuffer */
64#endif 64static int fb_defio; /* Optionally enable experimental fb_defio mmap support */
65
66#ifndef CONFIG_FB_SYS_IMAGEBLIT
67#ifndef CONFIG_FB_SYS_IMAGEBLIT_MODULE
68#warning Please set CONFIG_FB_SYS_IMAGEBLIT option to support fb console
69#endif
70#endif
71
72#ifndef CONFIG_FB_MODE_HELPERS
73#warning CONFIG_FB_MODE_HELPERS required. Expect build break
74#endif
75 65
76/* dlfb keeps a list of urbs for efficient bulk transfers */ 66/* dlfb keeps a list of urbs for efficient bulk transfers */
77static void dlfb_urb_completion(struct urb *urb); 67static void dlfb_urb_completion(struct urb *urb);
@@ -695,6 +685,68 @@ static void dlfb_ops_fillrect(struct fb_info *info,
695 685
696} 686}
697 687
688#ifdef CONFIG_FB_DEFERRED_IO
689/*
690 * NOTE: fb_defio.c is holding info->fbdefio.mutex
691 * Touching ANY framebuffer memory that triggers a page fault
692 * in fb_defio will cause a deadlock, when it also tries to
693 * grab the same mutex.
694 */
695static void dlfb_dpy_deferred_io(struct fb_info *info,
696 struct list_head *pagelist)
697{
698 struct page *cur;
699 struct fb_deferred_io *fbdefio = info->fbdefio;
700 struct dlfb_data *dev = info->par;
701 struct urb *urb;
702 char *cmd;
703 cycles_t start_cycles, end_cycles;
704 int bytes_sent = 0;
705 int bytes_identical = 0;
706 int bytes_rendered = 0;
707
708 if (!fb_defio)
709 return;
710
711 if (!atomic_read(&dev->usb_active))
712 return;
713
714 start_cycles = get_cycles();
715
716 urb = dlfb_get_urb(dev);
717 if (!urb)
718 return;
719
720 cmd = urb->transfer_buffer;
721
722 /* walk the written page list and render each to device */
723 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
724
725 dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
726 &cmd, cur->index << PAGE_SHIFT,
727 PAGE_SIZE, &bytes_identical, &bytes_sent);
728 bytes_rendered += PAGE_SIZE;
729 }
730
731 if (cmd > (char *) urb->transfer_buffer) {
732 /* Send partial buffer remaining before exiting */
733 int len = cmd - (char *) urb->transfer_buffer;
734 dlfb_submit_urb(dev, urb, len);
735 bytes_sent += len;
736 } else
737 dlfb_urb_completion(urb);
738
739 atomic_add(bytes_sent, &dev->bytes_sent);
740 atomic_add(bytes_identical, &dev->bytes_identical);
741 atomic_add(bytes_rendered, &dev->bytes_rendered);
742 end_cycles = get_cycles();
743 atomic_add(((unsigned int) ((end_cycles - start_cycles)
744 >> 10)), /* Kcycles */
745 &dev->cpu_kcycles_used);
746}
747
748#endif
749
698static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len) 750static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
699{ 751{
700 int i; 752 int i;
@@ -758,8 +810,6 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
758 if (area->y > info->var.yres) 810 if (area->y > info->var.yres)
759 area->y = info->var.yres; 811 area->y = info->var.yres;
760 812
761 atomic_set(&dev->use_defio, 0);
762
763 dlfb_handle_damage(dev, area->x, area->y, area->w, area->h, 813 dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
764 info->screen_base); 814 info->screen_base);
765 } 815 }
@@ -803,9 +853,13 @@ static int dlfb_ops_open(struct fb_info *info, int user)
803{ 853{
804 struct dlfb_data *dev = info->par; 854 struct dlfb_data *dev = info->par;
805 855
806/* if (user == 0) 856 /*
807 * We could special case kernel mode clients (fbcon) here 857 * fbcon aggressively connects to first framebuffer it finds,
808 */ 858 * preventing other clients (X) from working properly. Usually
859 * not what the user wants. Fail by default with option to enable.
860 */
861 if ((user == 0) & (!console))
862 return -EBUSY;
809 863
810 /* If the USB device is gone, we don't accept new opens */ 864 /* If the USB device is gone, we don't accept new opens */
811 if (dev->virtualized) 865 if (dev->virtualized)
@@ -816,7 +870,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
816 kref_get(&dev->kref); 870 kref_get(&dev->kref);
817 871
818#ifdef CONFIG_FB_DEFERRED_IO 872#ifdef CONFIG_FB_DEFERRED_IO
819 if ((atomic_read(&dev->use_defio)) && (info->fbdefio == NULL)) { 873 if (fb_defio && (info->fbdefio == NULL)) {
820 /* enable defio */ 874 /* enable defio */
821 info->fbdefio = &dlfb_defio; 875 info->fbdefio = &dlfb_defio;
822 fb_deferred_io_init(info); 876 fb_deferred_io_init(info);
@@ -1345,30 +1399,6 @@ static ssize_t metrics_reset_store(struct device *fbdev,
1345 return count; 1399 return count;
1346} 1400}
1347 1401
1348static ssize_t use_defio_show(struct device *fbdev,
1349 struct device_attribute *a, char *buf) {
1350 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1351 struct dlfb_data *dev = fb_info->par;
1352 return snprintf(buf, PAGE_SIZE, "%d\n",
1353 atomic_read(&dev->use_defio));
1354}
1355
1356static ssize_t use_defio_store(struct device *fbdev,
1357 struct device_attribute *attr,
1358 const char *buf, size_t count)
1359{
1360 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1361 struct dlfb_data *dev = fb_info->par;
1362
1363 if (count > 0) {
1364 if (buf[0] == '0')
1365 atomic_set(&dev->use_defio, 0);
1366 if (buf[0] == '1')
1367 atomic_set(&dev->use_defio, 1);
1368 }
1369 return count;
1370}
1371
1372static struct bin_attribute edid_attr = { 1402static struct bin_attribute edid_attr = {
1373 .attr.name = "edid", 1403 .attr.name = "edid",
1374 .attr.mode = 0666, 1404 .attr.mode = 0666,
@@ -1383,60 +1413,9 @@ static struct device_attribute fb_device_attrs[] = {
1383 __ATTR_RO(metrics_bytes_sent), 1413 __ATTR_RO(metrics_bytes_sent),
1384 __ATTR_RO(metrics_cpu_kcycles_used), 1414 __ATTR_RO(metrics_cpu_kcycles_used),
1385 __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store), 1415 __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
1386 __ATTR_RW(use_defio),
1387}; 1416};
1388 1417
1389#ifdef CONFIG_FB_DEFERRED_IO 1418#ifdef CONFIG_FB_DEFERRED_IO
1390static void dlfb_dpy_deferred_io(struct fb_info *info,
1391 struct list_head *pagelist)
1392{
1393 struct page *cur;
1394 struct fb_deferred_io *fbdefio = info->fbdefio;
1395 struct dlfb_data *dev = info->par;
1396 struct urb *urb;
1397 char *cmd;
1398 cycles_t start_cycles, end_cycles;
1399 int bytes_sent = 0;
1400 int bytes_identical = 0;
1401 int bytes_rendered = 0;
1402
1403 if (!atomic_read(&dev->use_defio))
1404 return;
1405
1406 if (!atomic_read(&dev->usb_active))
1407 return;
1408
1409 start_cycles = get_cycles();
1410
1411 urb = dlfb_get_urb(dev);
1412 if (!urb)
1413 return;
1414 cmd = urb->transfer_buffer;
1415
1416 /* walk the written page list and render each to device */
1417 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
1418 dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
1419 &cmd, cur->index << PAGE_SHIFT,
1420 PAGE_SIZE, &bytes_identical, &bytes_sent);
1421 bytes_rendered += PAGE_SIZE;
1422 }
1423
1424 if (cmd > (char *) urb->transfer_buffer) {
1425 /* Send partial buffer remaining before exiting */
1426 int len = cmd - (char *) urb->transfer_buffer;
1427 dlfb_submit_urb(dev, urb, len);
1428 bytes_sent += len;
1429 } else
1430 dlfb_urb_completion(urb);
1431
1432 atomic_add(bytes_sent, &dev->bytes_sent);
1433 atomic_add(bytes_identical, &dev->bytes_identical);
1434 atomic_add(bytes_rendered, &dev->bytes_rendered);
1435 end_cycles = get_cycles();
1436 atomic_add(((unsigned int) ((end_cycles - start_cycles)
1437 >> 10)), /* Kcycles */
1438 &dev->cpu_kcycles_used);
1439}
1440 1419
1441static struct fb_deferred_io dlfb_defio = { 1420static struct fb_deferred_io dlfb_defio = {
1442 .delay = 5, 1421 .delay = 5,
@@ -1563,6 +1542,8 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1563 dl_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n", 1542 dl_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
1564 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, 1543 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
1565 usbdev->descriptor.bcdDevice, dev); 1544 usbdev->descriptor.bcdDevice, dev);
1545 dl_info("console enable=%d\n", console);
1546 dl_info("fb_defio enable=%d\n", fb_defio);
1566 1547
1567 dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ 1548 dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
1568 1549
@@ -1611,9 +1592,6 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1611 1592
1612 /* ready to begin using device */ 1593 /* ready to begin using device */
1613 1594
1614#ifdef CONFIG_FB_DEFERRED_IO
1615 atomic_set(&dev->use_defio, 1);
1616#endif
1617 atomic_set(&dev->usb_active, 1); 1595 atomic_set(&dev->usb_active, 1);
1618 dlfb_select_std_channel(dev); 1596 dlfb_select_std_channel(dev);
1619 1597
@@ -1893,6 +1871,12 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
1893 return ret; 1871 return ret;
1894} 1872}
1895 1873
1874module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1875MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
1876
1877module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1878MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
1879
1896MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " 1880MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1897 "Jaya Kumar <jayakumar.lkml@gmail.com>, " 1881 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
1898 "Bernie Thompson <bernie@plugable.com>"); 1882 "Bernie Thompson <bernie@plugable.com>");
diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
index d28e783482d..58d2af6cebb 100644
--- a/drivers/staging/udlfb/udlfb.h
+++ b/drivers/staging/udlfb/udlfb.h
@@ -43,7 +43,6 @@ struct dlfb_data {
43 struct delayed_work free_framebuffer_work; 43 struct delayed_work free_framebuffer_work;
44 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 44 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
45 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ 45 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
46 atomic_t use_defio; /* 0 = rely on ioctls and blit/copy/fill rects */
47 char *edid; /* null until we read edid from hw or get from sysfs */ 46 char *edid; /* null until we read edid from hw or get from sysfs */
48 size_t edid_size; 47 size_t edid_size;
49 int sku_pixel_limit; 48 int sku_pixel_limit;