[PATCH 9/11] staging: udlfb: add module options for console and fb_defio

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxx>
Index: b/drivers/staging/udlfb/udlfb.c
===================================================================
--- a/drivers/staging/udlfb/udlfb.c	2010-08-18 11:21:05.000000000 -0700
+++ b/drivers/staging/udlfb/udlfb.c	2010-08-18 11:23:51.000000000 -0700
@@ -59,19 +59,9 @@ static struct usb_device_id id_table[] =
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-#ifndef CONFIG_FB_DEFERRED_IO
-#warning Please set CONFIG_FB_DEFFERRED_IO option to support generic fbdev apps
-#endif
-
-#ifndef CONFIG_FB_SYS_IMAGEBLIT
-#ifndef CONFIG_FB_SYS_IMAGEBLIT_MODULE
-#warning Please set CONFIG_FB_SYS_IMAGEBLIT option to support fb console
-#endif
-#endif
-
-#ifndef CONFIG_FB_MODE_HELPERS
-#warning CONFIG_FB_MODE_HELPERS required. Expect build break
-#endif
+/* module options */
+static int console;   /* Optionally allow fbcon to consume first framebuffer */
+static int fb_defio;  /* Optionally enable experimental fb_defio mmap support */
 
 /* dlfb keeps a list of urbs for efficient bulk transfers */
 static void dlfb_urb_completion(struct urb *urb);
@@ -695,6 +685,68 @@ static void dlfb_ops_fillrect(struct fb_
 
 }
 
+#ifdef CONFIG_FB_DEFERRED_IO
+/*
+ * NOTE: fb_defio.c is holding info->fbdefio.mutex
+ *   Touching ANY framebuffer memory that triggers a page fault
+ *   in fb_defio will cause a deadlock, when it also tries to
+ *   grab the same mutex.
+ */
+static void dlfb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct dlfb_data *dev = info->par;
+	struct urb *urb;
+	char *cmd;
+	cycles_t start_cycles, end_cycles;
+	int bytes_sent = 0;
+	int bytes_identical = 0;
+	int bytes_rendered = 0;
+
+	if (!fb_defio)
+		return;
+
+	if (!atomic_read(&dev->usb_active))
+		return;
+
+	start_cycles = get_cycles();
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return;
+
+	cmd = urb->transfer_buffer;
+
+	/* walk the written page list and render each to device */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+
+		dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+				  &cmd, cur->index << PAGE_SHIFT,
+				  PAGE_SIZE, &bytes_identical, &bytes_sent);
+		bytes_rendered += PAGE_SIZE;
+	}
+
+	if (cmd > (char *) urb->transfer_buffer) {
+		/* Send partial buffer remaining before exiting */
+		int len = cmd - (char *) urb->transfer_buffer;
+		dlfb_submit_urb(dev, urb, len);
+		bytes_sent += len;
+	} else
+		dlfb_urb_completion(urb);
+
+	atomic_add(bytes_sent, &dev->bytes_sent);
+	atomic_add(bytes_identical, &dev->bytes_identical);
+	atomic_add(bytes_rendered, &dev->bytes_rendered);
+	end_cycles = get_cycles();
+	atomic_add(((unsigned int) ((end_cycles - start_cycles)
+		    >> 10)), /* Kcycles */
+		   &dev->cpu_kcycles_used);
+}
+
+#endif
+
 static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
 {
 	int i;
@@ -758,8 +810,6 @@ static int dlfb_ops_ioctl(struct fb_info
 		if (area->y > info->var.yres)
 			area->y = info->var.yres;
 
-		atomic_set(&dev->use_defio, 0);
-
 		dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
 			   info->screen_base);
 	}
@@ -803,9 +853,13 @@ static int dlfb_ops_open(struct fb_info 
 {
 	struct dlfb_data *dev = info->par;
 
-/*	if (user == 0)
- *		We could special case kernel mode clients (fbcon) here
+	/*
+	 * fbcon aggressively connects to first framebuffer it finds,
+	 * preventing other clients (X) from working properly. Usually
+	 * not what the user wants. Fail by default with option to enable.
  */
+	if ((user == 0) & (!console))
+		return -EBUSY;
 
 	/* If the USB device is gone, we don't accept new opens */
 	if (dev->virtualized)
@@ -816,7 +870,7 @@ static int dlfb_ops_open(struct fb_info 
 	kref_get(&dev->kref);
 
 #ifdef CONFIG_FB_DEFERRED_IO
-	if ((atomic_read(&dev->use_defio)) && (info->fbdefio == NULL)) {
+	if (fb_defio && (info->fbdefio == NULL)) {
 		/* enable defio */
 		info->fbdefio = &dlfb_defio;
 		fb_deferred_io_init(info);
@@ -1345,30 +1399,6 @@ static ssize_t metrics_reset_store(struc
 	return count;
 }
 
-static ssize_t use_defio_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			atomic_read(&dev->use_defio));
-}
-
-static ssize_t use_defio_store(struct device *fbdev,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	if (count > 0) {
-		if (buf[0] == '0')
-			atomic_set(&dev->use_defio, 0);
-		if (buf[0] == '1')
-			atomic_set(&dev->use_defio, 1);
-	}
-	return count;
-}
-
 static struct bin_attribute edid_attr = {
 	.attr.name = "edid",
 	.attr.mode = 0666,
@@ -1383,60 +1413,9 @@ static struct device_attribute fb_device
 	__ATTR_RO(metrics_bytes_sent),
 	__ATTR_RO(metrics_cpu_kcycles_used),
 	__ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
-	__ATTR_RW(use_defio),
 };
 
 #ifdef CONFIG_FB_DEFERRED_IO
-static void dlfb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct dlfb_data *dev = info->par;
-	struct urb *urb;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	int bytes_rendered = 0;
-
-	if (!atomic_read(&dev->use_defio))
-		return;
-
-	if (!atomic_read(&dev->usb_active))
-		return;
-
-	start_cycles = get_cycles();
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return;
-	cmd = urb->transfer_buffer;
-
-	/* walk the written page list and render each to device */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
-				  &cmd, cur->index << PAGE_SHIFT,
-				  PAGE_SIZE, &bytes_identical, &bytes_sent);
-		bytes_rendered += PAGE_SIZE;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		dlfb_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		dlfb_urb_completion(urb);
-
-	atomic_add(bytes_sent, &dev->bytes_sent);
-	atomic_add(bytes_identical, &dev->bytes_identical);
-	atomic_add(bytes_rendered, &dev->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &dev->cpu_kcycles_used);
-}
 
 static struct fb_deferred_io dlfb_defio = {
 	.delay          = 5,
@@ -1563,6 +1542,8 @@ static int dlfb_usb_probe(struct usb_int
 	dl_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
 		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
 		usbdev->descriptor.bcdDevice, dev);
+	dl_info("console enable=%d\n", console);
+	dl_info("fb_defio enable=%d\n", fb_defio);
 
 	dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
 
@@ -1611,9 +1592,6 @@ static int dlfb_usb_probe(struct usb_int
 
 	/* ready to begin using device */
 
-#ifdef CONFIG_FB_DEFERRED_IO
-	atomic_set(&dev->use_defio, 1);
-#endif
 	atomic_set(&dev->usb_active, 1);
 	dlfb_select_std_channel(dev);
 
@@ -1893,6 +1871,12 @@ static int dlfb_submit_urb(struct dlfb_d
 	return ret;
 }
 
+module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
+
+module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
+
 MODULE_AUTHOR("Roberto De Ioris <roberto@xxxxxxxx>, "
 	      "Jaya Kumar <jayakumar.lkml@xxxxxxxxx>, "
 	      "Bernie Thompson <bernie@xxxxxxxxxxxx>");
Index: b/drivers/staging/udlfb/udlfb.h
===================================================================
--- a/drivers/staging/udlfb/udlfb.h	2010-08-18 11:17:48.000000000 -0700
+++ b/drivers/staging/udlfb/udlfb.h	2010-08-18 11:23:51.000000000 -0700
@@ -43,7 +43,6 @@ struct dlfb_data {
 	struct delayed_work free_framebuffer_work;
 	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
 	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
-	atomic_t use_defio; /* 0 = rely on ioctls and blit/copy/fill rects */
 	char *edid; /* null until we read edid from hw or get from sysfs */
 	size_t edid_size;
 	int sku_pixel_limit;


_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux