[kernel] r16526 - in dists/sid/linux-2.6/debian: . config patches/features/all/udlfb patches/series
Martin Michlmayr
tbm at alioth.debian.org
Tue Nov 2 20:21:29 UTC 2010
Author: tbm
Date: Tue Nov 2 20:21:21 2010
New Revision: 16526
Log:
Update udlfb to 2.6.36
Added:
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-dpms.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-slab.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-backup-edid-write.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-big-endian-fix.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-checkpatch-style.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-coding-style.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-enhance-edid.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fbdev-char.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fix-incorrect-fb_defio-implementation.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-minor-cleanups.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-module-options.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-remove-metrics_misc.patch
dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-revamp-reference-handling.patch
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/config/defines
dists/sid/linux-2.6/debian/patches/series/28
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog Tue Nov 2 16:36:34 2010 (r16525)
+++ dists/sid/linux-2.6/debian/changelog Tue Nov 2 20:21:21 2010 (r16526)
@@ -1,5 +1,6 @@
linux-2.6 (2.6.32-28) UNRELEASED; urgency=low
+ [ maximilian attems ]
* ipc: initialize structure memory to zero for shmctl.
* drm/i915: set DIDL using the ACPI video output device _ADR method return.
* images: Nuke modules.devname on removal. (closes: #590607)
@@ -8,6 +9,21 @@
* drm/nouveau: fix race condition when under memory pressure.
* [openvz] Update upstream patch to 2.6.32-dzhanibekov.
+ [ Martin Michlmayr ]
+ * Update udlfb to 2.6.36:
+ - udlfb: minor cleanups
+ - udlfb: fix coding style issues
+ - udlfb: fbdev character read and write support
+ - udlfb: add DPMS support
+ - udlfb: remove metrics_misc sysfs attribute
+ - udlfb: revamp reference handling to insure successful shutdown
+ - udlfb: enhance EDID and mode handling support
+ - udlfb: fix big endian rendering error
+ - udlfb: support for writing backup EDID to sysfs file
+ - udlfb: add module options for console and fb_defio
+ - udlfb: fix incorrect fb_defio implementation for multiple framebuffers
+ - udlfb: fix checkpatch and style
+
-- maximilian attems <maks at debian.org> Sat, 30 Oct 2010 14:14:37 +0200
linux-2.6 (2.6.32-27) unstable; urgency=high
Modified: dists/sid/linux-2.6/debian/config/defines
==============================================================================
--- dists/sid/linux-2.6/debian/config/defines Tue Nov 2 16:36:34 2010 (r16525)
+++ dists/sid/linux-2.6/debian/config/defines Tue Nov 2 20:21:21 2010 (r16526)
@@ -75,7 +75,7 @@
drivers/staging/rtl8192su/: 2.6.34
drivers/staging/rtl8192u/: 2.6.34
drivers/staging/samsung-laptop/: 2.6.35
-drivers/staging/udlfb/: 2.6.34
+drivers/staging/udlfb/: 2.6.36
drivers/usb/serial/usb_wwan.c: 2.6.34
drivers/usb/serial/usb-wwan.h: 2.6.34
drivers/staging/xgifb/: 2.6.35
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-dpms.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-dpms.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,85 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:10 +0000 (-0700)
+Subject: staging: udlfb: add DPMS support
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~680
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9825f70f5cf465a8c31236409456d18de07fd166
+
+staging: udlfb: add DPMS support
+
+Add ability to power off monitor with standard blanking interface
+
+Used by X servers and others to manage power of dislpay
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index a2bd5f7..0e03dd3 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -108,13 +108,16 @@ static char *dlfb_vidreg_unlock(char *buf)
+
+ /*
+ * On/Off for driving the DisplayLink framebuffer to the display
++ * 0x00 H and V sync on
++ * 0x01 H and V sync off (screen blank but powered)
++ * 0x07 DPMS powerdown (requires modeset to come back)
+ */
+ static char *dlfb_enable_hvsync(char *buf, bool enable)
+ {
+ if (enable)
+ return dlfb_set_register(buf, 0x1F, 0x00);
+ else
+- return dlfb_set_register(buf, 0x1F, 0x01);
++ return dlfb_set_register(buf, 0x1F, 0x07);
+ }
+
+ static char *dlfb_set_color_depth(char *buf, u8 selection)
+@@ -936,30 +939,31 @@ static int dlfb_ops_set_par(struct fb_info *info)
+ return dlfb_set_video_mode(dev, &info->var);
+ }
+
++/*
++ * In order to come back from full DPMS off, we need to set the mode again
++ */
+ static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+ {
+ struct dlfb_data *dev = info->par;
+- char *bufptr;
+- struct urb *urb;
+
+- urb = dlfb_get_urb(dev);
+- if (!urb)
+- return 0;
+- bufptr = (char *) urb->transfer_buffer;
++ if (blank_mode != FB_BLANK_UNBLANK) {
++ char *bufptr;
++ struct urb *urb;
+
+- /* overloading usb_active. UNBLANK can conflict with teardown */
++ urb = dlfb_get_urb(dev);
++ if (!urb)
++ return 0;
+
+- bufptr = dlfb_vidreg_lock(bufptr);
+- if (blank_mode != FB_BLANK_UNBLANK) {
+- atomic_set(&dev->usb_active, 0);
++ bufptr = (char *) urb->transfer_buffer;
++ bufptr = dlfb_vidreg_lock(bufptr);
+ bufptr = dlfb_enable_hvsync(bufptr, false);
++ bufptr = dlfb_vidreg_unlock(bufptr);
++
++ dlfb_submit_urb(dev, urb, bufptr -
++ (char *) urb->transfer_buffer);
+ } else {
+- atomic_set(&dev->usb_active, 1);
+- bufptr = dlfb_enable_hvsync(bufptr, true);
++ dlfb_set_video_mode(dev, &info->var);
+ }
+- bufptr = dlfb_vidreg_unlock(bufptr);
+-
+- dlfb_submit_urb(dev, urb, bufptr - (char *) urb->transfer_buffer);
+
+ return 0;
+ }
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-slab.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-add-slab.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,109 @@
+From: Tejun Heo <tj at kernel.org>
+Date: Wed, 24 Mar 2010 08:04:11 +0000 (+0900)
+Subject: include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
+X-Git-Tag: v2.6.34-rc4~71^2~5
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5a0e3ad6af8660be21ca98a971cd00f331318c05
+
+include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
+
+percpu.h is included by sched.h and module.h and thus ends up being
+included when building most .c files. percpu.h includes slab.h which
+in turn includes gfp.h making everything defined by the two files
+universally available and complicating inclusion dependencies.
+
+percpu.h -> slab.h dependency is about to be removed. Prepare for
+this change by updating users of gfp and slab facilities include those
+headers directly instead of assuming availability. As this conversion
+needs to touch large number of source files, the following script is
+used as the basis of conversion.
+
+ http://userweb.kernel.org/~tj/misc/slabh-sweep.py
+
+The script does the followings.
+
+* Scan files for gfp and slab usages and update includes such that
+ only the necessary includes are there. ie. if only gfp is used,
+ gfp.h, if slab is used, slab.h.
+
+* When the script inserts a new include, it looks at the include
+ blocks and try to put the new include such that its order conforms
+ to its surrounding. It's put in the include block which contains
+ core kernel includes, in the same order that the rest are ordered -
+ alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
+ doesn't seem to be any matching order.
+
+* If the script can't find a place to put a new include (mostly
+ because the file doesn't have fitting include block), it prints out
+ an error message indicating which .h file needs to be added to the
+ file.
+
+The conversion was done in the following steps.
+
+1. The initial automatic conversion of all .c files updated slightly
+ over 4000 files, deleting around 700 includes and adding ~480 gfp.h
+ and ~3000 slab.h inclusions. The script emitted errors for ~400
+ files.
+
+2. Each error was manually checked. Some didn't need the inclusion,
+ some needed manual addition while adding it to implementation .h or
+ embedding .c file was more appropriate for others. This step added
+ inclusions to around 150 files.
+
+3. The script was run again and the output was compared to the edits
+ from #2 to make sure no file was left behind.
+
+4. Several build tests were done and a couple of problems were fixed.
+ e.g. lib/decompress_*.c used malloc/free() wrappers around slab
+ APIs requiring slab.h to be added manually.
+
+5. The script was run on all .h files but without automatically
+ editing them as sprinkling gfp.h and slab.h inclusions around .h
+ files could easily lead to inclusion dependency hell. Most gfp.h
+ inclusion directives were ignored as stuff from gfp.h was usually
+ wildly available and often used in preprocessor macros. Each
+ slab.h inclusion directive was examined and added manually as
+ necessary.
+
+6. percpu.h was updated not to include slab.h.
+
+7. Build test were done on the following configurations and failures
+ were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
+ distributed build env didn't work with gcov compiles) and a few
+ more options had to be turned off depending on archs to make things
+ build (like ipr on powerpc/64 which failed due to missing writeq).
+
+ * x86 and x86_64 UP and SMP allmodconfig and a custom test config.
+ * powerpc and powerpc64 SMP allmodconfig
+ * sparc and sparc64 SMP allmodconfig
+ * ia64 SMP allmodconfig
+ * s390 SMP allmodconfig
+ * alpha SMP allmodconfig
+ * um on x86_64 SMP allmodconfig
+
+8. percpu.h modifications were reverted so that it could be applied as
+ a separate patch and serve as bisection point.
+
+Given the fact that I had only a couple of failures from tests on step
+6, I'm fairly confident about the coverage of this conversion patch.
+If there is a breakage, it's likely to be something in one of the arch
+headers which should be easily discoverable easily on most builds of
+the specific arch.
+
+Signed-off-by: Tejun Heo <tj at kernel.org>
+Guess-its-ok-by: Christoph Lameter <cl at linux-foundation.org>
+Cc: Ingo Molnar <mingo at redhat.com>
+Cc: Lee Schermerhorn <Lee.Schermerhorn at hp.com>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 8f6223c..a78ade0 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -24,6 +24,7 @@
+ #include <linux/mm.h>
+ #include <linux/fb.h>
+ #include <linux/vmalloc.h>
++#include <linux/slab.h>
+
+ #include "udlfb.h"
+
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-backup-edid-write.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-backup-edid-write.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,66 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:31 +0000 (-0700)
+Subject: staging: udlfb: support for writing backup EDID to sysfs file
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~675
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8ef8cc4fca4a92e77c0b5aa7a852a6c3d2fba844
+
+staging: udlfb: support for writing backup EDID to sysfs file
+
+Support writing default/backup edid via /sys/class/graphics/fb?/edid
+
+Writing a backup edid blob to the 'edid' file will cause udlfb to
+attempt to re-read the edid from hardware.
+If we still don't have a good edid, it will use the backup edid instead.
+The intent is to 1) enable user-supplied edid
+2) enable udev rules to backup the last known good edid
+for a device, and then provide that edid as a backup for all future starts
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index bcb4a1e9..b13869b 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -1304,6 +1304,27 @@
+ return count;
+ }
+
++static ssize_t edid_store(struct kobject *kobj, struct bin_attribute *a,
++ char *src, loff_t src_off, size_t src_size) {
++ struct device *fbdev = container_of(kobj, struct device, kobj);
++ struct fb_info *fb_info = dev_get_drvdata(fbdev);
++ struct dlfb_data *dev = fb_info->par;
++
++ /* We only support write of entire EDID at once, no offset*/
++ if ((src_size < MIN_EDID_SIZE) ||
++ (src_size > MAX_EDID_SIZE) ||
++ (src_off != 0))
++ return 0;
++
++ dlfb_setup_modes(dev, fb_info, src, src_size);
++
++ if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) {
++ dl_info("sysfs written EDID is new default\n");
++ dlfb_ops_set_par(fb_info);
++ return src_size;
++ } else
++ return 0;
++}
+
+ static ssize_t metrics_reset_store(struct device *fbdev,
+ struct device_attribute *attr,
+@@ -1346,9 +1367,10 @@
+
+ static struct bin_attribute edid_attr = {
+ .attr.name = "edid",
+- .attr.mode = 0444,
+- .size = 128,
++ .attr.mode = 0666,
++ .size = MAX_EDID_SIZE,
+ .read = edid_show,
++ .write = edid_store
+ };
+
+ static struct device_attribute fb_device_attrs[] = {
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-big-endian-fix.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-big-endian-fix.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,39 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:27 +0000 (-0700)
+Subject: staging: udlfb: fix big endian rendering error
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~676
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=1572f91cffd7c0d64ab4e0cec71e1d2d1a3349e1
+
+staging: udlfb: fix big endian rendering error
+
+Fix big endian rendering bug (affects PowerPC)
+
+Thanks to Christian Melki at Ericsson for finding and suggesting patch.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 6977b71..bcb4a1e9 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -414,15 +414,14 @@ static void dlfb_compress_hline(
+ uint8_t *cmd_pixels_count_byte = 0;
+ const uint16_t *raw_pixel_start = 0;
+ const uint16_t *cmd_pixel_start, *cmd_pixel_end = 0;
+- const uint32_t be_dev_addr = cpu_to_be32(dev_addr);
+
+ prefetchw((void *) cmd); /* pull in one cache line at least */
+
+ *cmd++ = 0xAF;
+ *cmd++ = 0x6B;
+- *cmd++ = (uint8_t) ((be_dev_addr >> 8) & 0xFF);
+- *cmd++ = (uint8_t) ((be_dev_addr >> 16) & 0xFF);
+- *cmd++ = (uint8_t) ((be_dev_addr >> 24) & 0xFF);
++ *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
++ *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
++ *cmd++ = (uint8_t) ((dev_addr) & 0xFF);
+
+ cmd_pixels_count_byte = cmd++; /* we'll know this later */
+ cmd_pixel_start = pixel;
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-checkpatch-style.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-checkpatch-style.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,94 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Mon, 6 Sep 2010 01:29:56 +0000 (-0700)
+Subject: staging: udlfb: fix checkpatch and style
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~664
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=2685cffa9e799278cdbfa5f524dd9e548be6598d
+
+staging: udlfb: fix checkpatch and style
+
+Fix warnings detected by tools
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 082468a..5969e84 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -27,7 +27,6 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+
+-
+ #include "udlfb.h"
+
+ static struct fb_fix_screeninfo dlfb_fix = {
+@@ -256,6 +255,7 @@ static int dlfb_set_video_mode(struct dlfb_data *dev,
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return -ENOMEM;
++
+ buf = (char *) urb->transfer_buffer;
+
+ /*
+@@ -288,13 +288,14 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long page, pos;
+
+- dl_notice("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
+-
+ if (offset + size > info->fix.smem_len)
+ return -EINVAL;
+
+ pos = (unsigned long)info->fix.smem_start + offset;
+
++ dl_notice("mmap() framebuffer addr:%lu size:%lu\n",
++ pos, size);
++
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+@@ -310,7 +311,6 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ return 0;
+-
+ }
+
+ /*
+@@ -372,13 +372,13 @@ static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
+ * A single command can transmit a maximum of 256 pixels,
+ * regardless of the compression ratio (protocol design limit).
+ * To the hardware, 0 for a size byte means 256
+- *
++ *
+ * Rather than 256 pixel commands which are either rl or raw encoded,
+ * the rlx command simply assumes alternating raw and rl spans within one cmd.
+ * This has a slightly larger header overhead, but produces more even results.
+ * It also processes all data (read and write) in a single pass.
+ * Performance benchmarks of common cases show it having just slightly better
+- * compression than 256 pixel raw -or- rle commands, with similar CPU consumpion.
++ * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
+ * But for very rl friendly data, will compress not quite as well.
+ */
+ static void dlfb_compress_hline(
+@@ -570,7 +570,7 @@ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+
+ if (dlfb_render_hline(dev, &urb,
+ (char *) dev->info->fix.smem_start,
+- &cmd, byte_offset, width * BPP,
++ &cmd, byte_offset, width * BPP,
+ &bytes_identical, &bytes_sent))
+ goto error;
+ }
+@@ -1532,8 +1532,8 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ struct usb_device *usbdev;
+ struct dlfb_data *dev = 0;
+ struct fb_info *info = 0;
+- int i;
+ int retval = -ENOMEM;
++ int i;
+
+ /* usb initialization */
+
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-coding-style.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-coding-style.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,38 @@
+From: Soeren Moeller <soerenmoeller2001 at gmail.com>
+Date: Fri, 14 May 2010 19:03:00 +0000 (+0000)
+Subject: Staging: udlfb: fix coding style issues
+X-Git-Tag: v2.6.35-rc1~441^2^2~27
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=b5a2104c98cb603f7053e4b0309fb88f15d6be86
+
+Staging: udlfb: fix coding style issues
+
+This is a patch to the file udlfb.c that fixes a missing KERN_INFO and
+removes one whitespace before a newline.
+
+Signed-off-by: Soeren Moeller <soerenmoeller2001 at gmail.com>
+Cc: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 12444f2..7fc1d61 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -1438,7 +1438,7 @@ static int __init dlfb_module_init(void)
+ if (res)
+ err("usb_register failed. Error number %d", res);
+
+- printk("VMODES initialized\n");
++ printk(KERN_INFO "VMODES initialized\n");
+
+ return res;
+ }
+@@ -1567,7 +1567,7 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+
+ kref_get(&dev->kref); /* released in free_render_urbs() */
+
+- dl_notice("allocated %d %d byte urbs \n", i, (int) size);
++ dl_notice("allocated %d %d byte urbs\n", i, (int) size);
+
+ return i;
+ }
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-enhance-edid.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-enhance-edid.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,604 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:23 +0000 (-0700)
+Subject: staging: udlfb: enhance EDID and mode handling support
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~677
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=18dffdf8913ab9e4ac7403a624879a15afa5262e
+
+staging: udlfb: enhance EDID and mode handling support
+
+Enhance EDID and mode table handling
+
+* Adds support for lower-end DL chips on higher-end monitors
+* Adds support for using fbdev standard EDID parsing and handling
+* Adds support for more dynamic reallocation of framebuffer, based on new EDID
+
+Queries EDID from hardware with several retries then
+queries DisplayLink chip for max pixel area via vendor descriptor.
+Uses existing fbdev mode handling service funcations to build mode list
+of common modes between adapter and monitor.
+This enables lower-end chips (e.g. DL-125) to successfully pick a compatible
+mode on higher end monitors (e.g. whose default mode is over 1280x1024).
+Reallocate framebuffer if necessary in response to new max mode.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index c9ac687..6977b71 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -696,19 +696,32 @@
+
+ }
+
+-static void dlfb_get_edid(struct dlfb_data *dev)
++static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
+ {
+ int i;
+ int ret;
+- char rbuf[2];
++ char *rbuf;
+
+- for (i = 0; i < sizeof(dev->edid); i++) {
++ rbuf = kmalloc(2, GFP_KERNEL);
++ if (!rbuf)
++ return 0;
++
++ for (i = 0; i < len; i++) {
+ ret = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0), (0x02),
+ (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
+- 0);
+- dev->edid[i] = rbuf[1];
++ HZ);
++ if (ret < 1) {
++ dl_err("Read EDID byte %d failed err %x\n", i, ret);
++ i--;
++ break;
++ }
++ edid[i] = rbuf[1];
+ }
++
++ kfree(rbuf);
++
++ return i;
+ }
+
+ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+@@ -724,8 +737,7 @@
+ /* TODO: Update X server to get this from sysfs instead */
+ if (cmd == DLFB_IOCTL_RETURN_EDID) {
+ char *edid = (char *)arg;
+- dlfb_get_edid(dev);
+- if (copy_to_user(edid, dev->edid, sizeof(dev->edid)))
++ if (copy_to_user(edid, dev->edid, dev->edid_size))
+ return -EFAULT;
+ return 0;
+ }
+@@ -910,8 +922,13 @@
+ {
+ struct dlfb_data *dev = info->par;
+
+- if (mode->xres * mode->yres > dev->sku_pixel_limit)
++ if (mode->xres * mode->yres > dev->sku_pixel_limit) {
++ dl_warn("%dx%d beyond chip capabilities\n",
++ mode->xres, mode->yres);
+ return 0;
++ }
++
++ dl_info("%dx%d valid mode\n", mode->xres, mode->yres);
+
+ return 1;
+ }
+@@ -951,10 +968,27 @@
+ static int dlfb_ops_set_par(struct fb_info *info)
+ {
+ struct dlfb_data *dev = info->par;
++ int result;
++ u16 *pix_framebuffer;
++ int i;
+
+ dl_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
+
+- return dlfb_set_video_mode(dev, &info->var);
++ result = dlfb_set_video_mode(dev, &info->var);
++
++ if ((result == 0) && (dev->fb_count == 0)) {
++
++ /* paint greenscreen */
++
++ pix_framebuffer = (u16 *) info->screen_base;
++ for (i = 0; i < info->fix.smem_len / 2; i++)
++ pix_framebuffer[i] = 0x37e6;
++
++ dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
++ info->screen_base);
++ }
++
++ return result;
+ }
+
+ /*
+@@ -1003,46 +1037,166 @@
+ .fb_set_par = dlfb_ops_set_par,
+ };
+
++
++/*
++ * Assumes &info->lock held by caller
++ * Assumes no active clients have framebuffer open
++ */
++static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
++{
++ int retval = -ENOMEM;
++ int old_len = info->fix.smem_len;
++ int new_len;
++ unsigned char *old_fb = info->screen_base;
++ unsigned char *new_fb;
++ unsigned char *new_back;
++
++ dl_warn("Reallocating framebuffer. Addresses will change!\n");
++
++ new_len = info->fix.line_length * info->var.yres;
++
++ if (PAGE_ALIGN(new_len) > old_len) {
++ /*
++ * Alloc system memory for virtual framebuffer
++ */
++ new_fb = vmalloc(new_len);
++ if (!new_fb) {
++ dl_err("Virtual framebuffer alloc failed\n");
++ goto error;
++ }
++
++ if (info->screen_base) {
++ memcpy(new_fb, old_fb, old_len);
++ vfree(info->screen_base);
++ }
++
++ info->screen_base = new_fb;
++ info->fix.smem_len = PAGE_ALIGN(new_len);
++ info->fix.smem_start = (unsigned long) new_fb;
++ info->flags = udlfb_info_flags;
++
++ /*
++ * Second framebuffer copy to mirror the framebuffer state
++ * on the physical USB device. We can function without this.
++ * But with imperfect damage info we may send pixels over USB
++ * that were, in fact, unchanged - wasting limited USB bandwidth
++ */
++ new_back = vmalloc(new_len);
++ if (!new_back)
++ dl_info("No shadow/backing buffer allcoated\n");
++ else {
++ if (dev->backing_buffer)
++ vfree(dev->backing_buffer);
++ dev->backing_buffer = new_back;
++ memset(dev->backing_buffer, 0, new_len);
++ }
++ }
++
++ retval = 0;
++
++error:
++ return retval;
++}
++
+ /*
+- * Calls dlfb_get_edid() to query the EDID of attached monitor via usb cmds
+- * Then parses EDID into three places used by various parts of fbdev:
++ * 1) Get EDID from hw, or use sw default
++ * 2) Parse into various fb_info structs
++ * 3) Allocate virtual framebuffer memory to back highest res mode
++ *
++ * Parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+- * Returns 0 if EDID parses successfully
++ * Returns 0 if successful
+ */
+-static int dlfb_parse_edid(struct dlfb_data *dev,
+- struct fb_var_screeninfo *var,
+- struct fb_info *info)
++static int dlfb_setup_modes(struct dlfb_data *dev,
++ struct fb_info *info,
++ char *default_edid, size_t default_edid_size)
+ {
+ int i;
+ const struct fb_videomode *default_vmode = NULL;
+ int result = 0;
++ char *edid;
++ int tries = 3;
++
++ if (info->dev) /* only use mutex if info has been registered */
++ mutex_lock(&info->lock);
++
++ edid = kmalloc(MAX_EDID_SIZE, GFP_KERNEL);
++ if (!edid) {
++ result = -ENOMEM;
++ goto error;
++ }
+
+ fb_destroy_modelist(&info->modelist);
+ memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+- dlfb_get_edid(dev);
+- fb_edid_to_monspecs(dev->edid, &info->monspecs);
++ /*
++ * Try to (re)read EDID from hardware first
++ * EDID data may return, but not parse as valid
++ * Try again a few times, in case of e.g. analog cable noise
++ */
++ while (tries--) {
++
++ i = dlfb_get_edid(dev, edid, MAX_EDID_SIZE);
++
++ if (i >= MIN_EDID_SIZE)
++ fb_edid_to_monspecs(edid, &info->monspecs);
++
++ if (info->monspecs.modedb_len > 0) {
++ dev->edid = edid;
++ dev->edid_size = i;
++ break;
++ }
++ }
++
++ /* If that fails, use a previously returned EDID if available */
++ if (info->monspecs.modedb_len == 0) {
++
++ dl_err("Unable to get valid EDID from device/display\n");
++
++ if (dev->edid) {
++ fb_edid_to_monspecs(dev->edid, &info->monspecs);
++ if (info->monspecs.modedb_len > 0)
++ dl_err("Using previously queried EDID\n");
++ }
++ }
++
++ /* If that fails, use the default EDID we were handed */
++ if (info->monspecs.modedb_len == 0) {
++ if (default_edid_size >= MIN_EDID_SIZE) {
++ fb_edid_to_monspecs(default_edid, &info->monspecs);
++ if (info->monspecs.modedb_len > 0) {
++ memcpy(edid, default_edid, default_edid_size);
++ dev->edid = edid;
++ dev->edid_size = default_edid_size;
++ dl_err("Using default/backup EDID\n");
++ }
++ }
++ }
+
++ /* If we've got modes, let's pick a best default mode */
+ if (info->monspecs.modedb_len > 0) {
+
+ for (i = 0; i < info->monspecs.modedb_len; i++) {
+ if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
+ fb_add_videomode(&info->monspecs.modedb[i],
+ &info->modelist);
++ else /* if we've removed top/best mode */
++ info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
+ }
+
+ default_vmode = fb_find_best_display(&info->monspecs,
+ &info->modelist);
+- } else {
+- struct fb_videomode fb_vmode = {0};
++ }
+
+- dl_err("Unable to get valid EDID from device/display\n");
+- result = 1;
++ /* If everything else has failed, fall back to safe default mode */
++ if (default_vmode == NULL) {
++
++ struct fb_videomode fb_vmode = {0};
+
+ /*
+ * Add the standard VESA modes to our modelist
+@@ -1068,8 +1222,30 @@
+ &info->modelist);
+ }
+
+- fb_videomode_to_var(var, default_vmode);
+- dlfb_var_color_format(var);
++ /* If we have good mode and no active clients*/
++ if ((default_vmode != NULL) && (dev->fb_count == 0)) {
++
++ fb_videomode_to_var(&info->var, default_vmode);
++ dlfb_var_color_format(&info->var);
++
++ /*
++ * with mode size info, we can now alloc our framebuffer.
++ */
++ memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
++ info->fix.line_length = info->var.xres *
++ (info->var.bits_per_pixel / 8);
++
++ result = dlfb_realloc_framebuffer(dev, info);
++
++ } else
++ result = -EINVAL;
++
++error:
++ if (edid && (dev->edid != edid))
++ kfree(edid);
++
++ if (info->dev)
++ mutex_unlock(&info->lock);
+
+ return result;
+ }
+@@ -1111,18 +1287,20 @@
+ struct device *fbdev = container_of(kobj, struct device, kobj);
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+- char *edid = &dev->edid[0];
+- const size_t size = sizeof(dev->edid);
+
+- if (dlfb_parse_edid(dev, &fb_info->var, fb_info))
++ if (dev->edid == NULL)
+ return 0;
+
+- if (off >= size)
++ if ((off >= dev->edid_size) || (count > dev->edid_size))
+ return 0;
+
+- if (off + count > size)
+- count = size - off;
+- memcpy(buf, edid + off, count);
++ if (off + count > dev->edid_size)
++ count = dev->edid_size - off;
++
++ dl_info("sysfs edid copy %p to %p, %d bytes\n",
++ dev->edid, buf, (int) count);
++
++ memcpy(buf, dev->edid, count);
+
+ return count;
+ }
+@@ -1260,19 +1438,82 @@
+ return ret;
+ }
+
++static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
++ struct usb_device *usbdev)
++{
++ char *desc;
++ char *buf;
++ char *desc_end;
+
++ u8 total_len = 0;
++
++ buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
++ if (!buf)
++ return false;
++ desc = buf;
++
++ total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
++ 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
++ if (total_len > 5) {
++ dl_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
++ "%02x %02x %02x %02x %02x %02x %02x\n",
++ total_len, desc[0],
++ desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
++ desc[7], desc[8], desc[9], desc[10]);
++
++ if ((desc[0] != total_len) || /* descriptor length */
++ (desc[1] != 0x5f) || /* vendor descriptor type */
++ (desc[2] != 0x01) || /* version (2 bytes) */
++ (desc[3] != 0x00) ||
++ (desc[4] != total_len - 2)) /* length after type */
++ goto unrecognized;
++
++ desc_end = desc + total_len;
++ desc += 5; /* the fixed header we've already parsed */
++
++ while (desc < desc_end) {
++ u8 length;
++ u16 key;
++
++ key = *((u16 *) desc);
++ desc += sizeof(u16);
++ length = *desc;
++ desc++;
++
++ switch (key) {
++ case 0x0200: { /* max_area */
++ u32 max_area;
++ max_area = le32_to_cpu(*((u32 *)desc));
++ dl_warn("DL chip limited to %d pixel modes\n",
++ max_area);
++ dev->sku_pixel_limit = max_area;
++ break;
++ }
++ default:
++ break;
++ }
++ desc += length;
++ }
++ }
++
++ goto success;
++
++unrecognized:
++ /* allow udlfb to load for now even if firmware unrecognized */
++ dl_err("Unrecognized vendor firmware descriptor\n");
++
++success:
++ kfree(buf);
++ return true;
++}
+ static int dlfb_usb_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+ {
+ struct usb_device *usbdev;
+- struct dlfb_data *dev;
++ struct dlfb_data *dev = 0;
+ struct fb_info *info = 0;
+- int videomemorysize;
+ int i;
+- unsigned char *videomemory;
+ int retval = -ENOMEM;
+- struct fb_var_screeninfo *var;
+- u16 *pix_framebuffer;
+
+ /* usb initialization */
+
+@@ -1286,12 +1527,25 @@
+
+ /* we need to wait for both usb and fbdev to spin down on disconnect */
+ kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+- kref_get(&dev->kref); /* matching kref_put in .fb_destroy function*/
++ kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
+
+ dev->udev = usbdev;
+ dev->gdev = &usbdev->dev; /* our generic struct device * */
+ usb_set_intfdata(interface, dev);
+
++ dl_info("%s %s - serial #%s\n",
++ usbdev->manufacturer, usbdev->product, usbdev->serial);
++ 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);
++
++ dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
++
++ if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
++ dl_err("firmware not recognized. Assume incompatible device\n");
++ goto error;
++ }
++
+ if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+ retval = -ENOMEM;
+ dl_err("dlfb_alloc_urb_list failed\n");
+@@ -1313,50 +1567,6 @@
+ info->pseudo_palette = dev->pseudo_palette;
+ info->fbops = &dlfb_ops;
+
+- var = &info->var;
+-
+- /* TODO set limit based on actual SKU detection */
+- dev->sku_pixel_limit = 2048 * 1152;
+-
+- INIT_LIST_HEAD(&info->modelist);
+- dlfb_parse_edid(dev, var, info);
+-
+- /*
+- * ok, now that we've got the size info, we can alloc our framebuffer.
+- */
+- info->fix = dlfb_fix;
+- info->fix.line_length = var->xres * (var->bits_per_pixel / 8);
+- videomemorysize = info->fix.line_length * var->yres;
+-
+- /*
+- * The big chunk of system memory we use as a virtual framebuffer.
+- * TODO: Handle fbcon cursor code calling blit in interrupt context
+- */
+- videomemory = vmalloc(videomemorysize);
+- if (!videomemory) {
+- retval = -ENOMEM;
+- dl_err("Virtual framebuffer alloc failed\n");
+- goto error;
+- }
+-
+- info->screen_base = videomemory;
+- info->fix.smem_len = PAGE_ALIGN(videomemorysize);
+- info->fix.smem_start = (unsigned long) videomemory;
+- info->flags = udlfb_info_flags;
+-
+-
+- /*
+- * Second framebuffer copy, mirroring the state of the framebuffer
+- * on the physical USB device. We can function without this.
+- * But with imperfect damage info we may end up sending pixels over USB
+- * that were, in fact, unchanged -- wasting limited USB bandwidth
+- */
+- dev->backing_buffer = vmalloc(videomemorysize);
+- if (!dev->backing_buffer)
+- dl_warn("No shadow/backing buffer allcoated\n");
+- else
+- memset(dev->backing_buffer, 0, videomemorysize);
+-
+ retval = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (retval < 0) {
+ dl_err("fb_alloc_cmap failed %x\n", retval);
+@@ -1366,6 +1576,14 @@
+ INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+ dlfb_free_framebuffer_work);
+
++ INIT_LIST_HEAD(&info->modelist);
++
++ retval = dlfb_setup_modes(dev, info, NULL, 0);
++ if (retval != 0) {
++ dl_err("unable to find common mode for display and adapter\n");
++ goto error;
++ }
++
+ /* ready to begin using device */
+
+ #ifdef CONFIG_FB_DEFERRED_IO
+@@ -1374,17 +1592,9 @@
+ atomic_set(&dev->usb_active, 1);
+ dlfb_select_std_channel(dev);
+
+- dlfb_ops_check_var(var, info);
++ dlfb_ops_check_var(&info->var, info);
+ dlfb_ops_set_par(info);
+
+- /* paint greenscreen */
+- pix_framebuffer = (u16 *) videomemory;
+- for (i = 0; i < videomemorysize / 2; i++)
+- pix_framebuffer[i] = 0x37e6;
+-
+- dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
+- videomemory);
+-
+ retval = register_framebuffer(info);
+ if (retval < 0) {
+ dl_err("register_framebuffer failed %d\n", retval);
+@@ -1396,11 +1606,11 @@
+
+ device_create_bin_file(info->dev, &edid_attr);
+
+- dl_err("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
++ dl_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
+ " Using %dK framebuffer memory\n", info->node,
+- var->xres, var->yres,
++ info->var.xres, info->var.yres,
+ ((dev->backing_buffer) ?
+- videomemorysize * 2 : videomemorysize) >> 10);
++ info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
+ return 0;
+
+ error:
+
+diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
+index 7c46477..d28e783 100644
+--- a/drivers/staging/udlfb/udlfb.h
++++ b/drivers/staging/udlfb/udlfb.h
+@@ -44,7 +44,8 @@ struct dlfb_data {
+ 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[128];
++ char *edid; /* null until we read edid from hw or get from sysfs */
++ size_t edid_size;
+ int sku_pixel_limit;
+ int base16;
+ int base8;
+@@ -64,6 +65,11 @@ struct dlfb_data {
+ #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
+ #define WRITES_IN_FLIGHT (4)
+
++#define MIN_EDID_SIZE 128
++#define MAX_EDID_SIZE 128
++
++#define MAX_VENDOR_DESCRIPTOR_SIZE 256
++
+ #define GET_URB_TIMEOUT HZ
+ #define FREE_URB_TIMEOUT (HZ*2)
+
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fbdev-char.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fbdev-char.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,81 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:04 +0000 (-0700)
+Subject: staging: udlfb: fbdev character read and write support
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~681
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=d46ecb9f79db82ce6bef4baafbcae29ac809ea67
+
+staging: udlfb: fbdev character read and write support
+
+Restore fbdev character read and write support
+
+Enables access to the framebuffer from simple reads and writes
+to /dev/fb0 (or fb1, ...). Low performance, because of extra copy
+and because udlfb must scan every pixel for changes. But very
+useful for testing and simple image display, etc.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index c7e061e..a2bd5f7 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -602,6 +602,48 @@ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+ return 0;
+ }
+
++static ssize_t dlfb_ops_read(struct fb_info *info, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t result = -ENOSYS;
++
++#if defined CONFIG_FB_SYS_FOPS || defined CONFIG_FB_SYS_FOPS_MODULE
++ result = fb_sys_read(info, buf, count, ppos);
++#endif
++
++ return result;
++}
++
++/*
++ * Path triggered by usermode clients who write to filesystem
++ * e.g. cat filename > /dev/fb1
++ * Not used by X Windows or text-mode console. But useful for testing.
++ * Slow because of extra copy and we must assume all pixels dirty.
++ */
++static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t result = -ENOSYS;
++ struct dlfb_data *dev = info->par;
++ u32 offset = (u32) *ppos;
++
++#if defined CONFIG_FB_SYS_FOPS || defined CONFIG_FB_SYS_FOPS_MODULE
++
++ result = fb_sys_write(info, buf, count, ppos);
++
++ if (result > 0) {
++ int start = max((int)(offset / info->fix.line_length) - 1, 0);
++ int lines = min((u32)((result / info->fix.line_length) + 1),
++ (u32)info->var.yres);
++
++ dlfb_handle_damage(dev, 0, start, info->var.xres,
++ lines, info->screen_base);
++ }
++#endif
++
++ return result;
++}
++
+ /* hardware has native COPY command (see libdlo), but not worth it for fbcon */
+ static void dlfb_ops_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+@@ -924,6 +966,8 @@ static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+
+ static struct fb_ops dlfb_ops = {
+ .owner = THIS_MODULE,
++ .fb_read = dlfb_ops_read,
++ .fb_write = dlfb_ops_write,
+ .fb_setcolreg = dlfb_ops_setcolreg,
+ .fb_fillrect = dlfb_ops_fillrect,
+ .fb_copyarea = dlfb_ops_copyarea,
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fix-incorrect-fb_defio-implementation.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-fix-incorrect-fb_defio-implementation.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,236 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Mon, 6 Sep 2010 01:28:29 +0000 (-0700)
+Subject: staging: udlfb: fix incorrect fb_defio implementation for multiple framebuffers
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~665
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5bea1fbf942363e4114a086aefc67cdca21be7f0
+
+staging: udlfb: fix incorrect fb_defio implementation for multiple framebuffers
+
+Fix fb_defio bug in udlfb for multiple framebuffers
+
+Previously when using fb_defio with multiple DisplayLink attached displays
+udlfb incorrectly used a shared datastructure where it needed to have
+one per fb_info struct. This was completely broken and caused all kinds of
+problems, including rendering to one framebuffer affecting others.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 80a1e0e..082468a 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -70,11 +70,6 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
+ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
+ static void dlfb_free_urb_list(struct dlfb_data *dev);
+
+-/* other symbols with dependents */
+-#ifdef CONFIG_FB_DEFERRED_IO
+-static struct fb_deferred_io dlfb_defio;
+-#endif
+-
+ /*
+ * All DisplayLink bulk operations start with 0xAF, followed by specific code
+ * All operations are written to buffers which then later get sent to device
+@@ -481,7 +476,7 @@ static void dlfb_compress_hline(
+ * (that we can only write to, slowly, and can never read), and (optionally)
+ * our shadow copy that tracks what's been sent to that hardware buffer.
+ */
+-static void dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
++static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+ const char *front, char **urb_buf_ptr,
+ u32 byte_offset, u32 byte_width,
+ int *ident_ptr, int *sent_ptr)
+@@ -523,11 +518,11 @@ static void dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+ if (cmd >= cmd_end) {
+ int len = cmd - (u8 *) urb->transfer_buffer;
+ if (dlfb_submit_urb(dev, urb, len))
+- return; /* lost pixels is set */
++ return 1; /* lost pixels is set */
+ *sent_ptr += len;
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+- return; /* lost_pixels is set */
++ return 1; /* lost_pixels is set */
+ *urb_ptr = urb;
+ cmd = urb->transfer_buffer;
+ cmd_end = &cmd[urb->transfer_buffer_length];
+@@ -535,6 +530,8 @@ static void dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+ }
+
+ *urb_buf_ptr = cmd;
++
++ return 0;
+ }
+
+ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+@@ -571,9 +568,11 @@ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+ const int line_offset = dev->info->fix.line_length * i;
+ const int byte_offset = line_offset + (x * BPP);
+
+- dlfb_render_hline(dev, &urb, (char *) dev->info->fix.smem_start,
++ if (dlfb_render_hline(dev, &urb,
++ (char *) dev->info->fix.smem_start,
+ &cmd, byte_offset, width * BPP,
+- &bytes_identical, &bytes_sent);
++ &bytes_identical, &bytes_sent))
++ goto error;
+ }
+
+ if (cmd > (char *) urb->transfer_buffer) {
+@@ -584,6 +583,7 @@ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+ } else
+ dlfb_urb_completion(urb);
+
++error:
+ atomic_add(bytes_sent, &dev->bytes_sent);
+ atomic_add(bytes_identical, &dev->bytes_identical);
+ atomic_add(width*height*2, &dev->bytes_rendered);
+@@ -722,9 +722,10 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
+ /* 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,
++ if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+ &cmd, cur->index << PAGE_SHIFT,
+- PAGE_SIZE, &bytes_identical, &bytes_sent);
++ PAGE_SIZE, &bytes_identical, &bytes_sent))
++ goto error;
+ bytes_rendered += PAGE_SIZE;
+ }
+
+@@ -736,6 +737,7 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
+ } else
+ dlfb_urb_completion(urb);
+
++error:
+ atomic_add(bytes_sent, &dev->bytes_sent);
+ atomic_add(bytes_identical, &dev->bytes_identical);
+ atomic_add(bytes_rendered, &dev->bytes_rendered);
+@@ -796,6 +798,16 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+ /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+ if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
+
++ /*
++ * If we have a damage-aware client, turn fb_defio "off"
++ * To avoid perf imact of unecessary page fault handling.
++ * Done by resetting the delay for this fb_info to a very
++ * long period. Pages will become writable and stay that way.
++ * Reset to normal value when all clients have closed this fb.
++ */
++ if (info->fbdefio)
++ info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
++
+ area = (struct dloarea *)arg;
+
+ if (area->x < 0)
+@@ -871,8 +883,18 @@ static int dlfb_ops_open(struct fb_info *info, int user)
+
+ #ifdef CONFIG_FB_DEFERRED_IO
+ if (fb_defio && (info->fbdefio == NULL)) {
+- /* enable defio */
+- info->fbdefio = &dlfb_defio;
++ /* enable defio at last moment if not disabled by client */
++
++ struct fb_deferred_io *fbdefio;
++
++ fbdefio = kmalloc(GFP_KERNEL, sizeof(struct fb_deferred_io));
++
++ if (fbdefio) {
++ fbdefio->delay = DL_DEFIO_WRITE_DELAY;
++ fbdefio->deferred_io = dlfb_dpy_deferred_io;
++ }
++
++ info->fbdefio = fbdefio;
+ fb_deferred_io_init(info);
+ }
+ #endif
+@@ -906,6 +928,13 @@ static void dlfb_free(struct kref *kref)
+ kfree(dev);
+ }
+
++static void dlfb_release_urb_work(struct work_struct *work)
++{
++ struct urb_node *unode = container_of(work, struct urb_node,
++ release_urb_work.work);
++
++ up(&unode->dev->urbs.limit_sem);
++}
+
+ static void dlfb_free_framebuffer_work(struct work_struct *work)
+ {
+@@ -1411,15 +1440,6 @@ static struct device_attribute fb_device_attrs[] = {
+ __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
+ };
+
+-#ifdef CONFIG_FB_DEFERRED_IO
+-
+-static struct fb_deferred_io dlfb_defio = {
+- .delay = 5,
+- .deferred_io = dlfb_dpy_deferred_io,
+-};
+-
+-#endif
+-
+ /*
+ * This is necessary before we can communicate with the display controller.
+ */
+@@ -1726,7 +1746,14 @@ static void dlfb_urb_completion(struct urb *urb)
+ dev->urbs.available++;
+ spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+- up(&dev->urbs.limit_sem);
++ /*
++ * When using fb_defio, we deadlock if up() is called
++ * while another is waiting. So queue to another process.
++ */
++ if (fb_defio)
++ schedule_delayed_work(&unode->release_urb_work, 0);
++ else
++ up(&dev->urbs.limit_sem);
+ }
+
+ static void dlfb_free_urb_list(struct dlfb_data *dev)
+@@ -1785,6 +1812,9 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+ break;
+ unode->dev = dev;
+
++ INIT_DELAYED_WORK(&unode->release_urb_work,
++ dlfb_release_urb_work);
++
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(unode);
+@@ -1831,7 +1861,8 @@ static struct urb *dlfb_get_urb(struct dlfb_data *dev)
+ ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+ if (ret) {
+ atomic_set(&dev->lost_pixels, 1);
+- dl_err("wait for urb interrupted: %x\n", ret);
++ dl_warn("wait for urb interrupted: %x available: %d\n",
++ ret, dev->urbs.available);
+ goto error;
+ }
+
+diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
+index 58d2af6..6f9785e 100644
+--- a/drivers/staging/udlfb/udlfb.h
++++ b/drivers/staging/udlfb/udlfb.h
+@@ -19,6 +19,7 @@ struct dloarea {
+ struct urb_node {
+ struct list_head entry;
+ struct dlfb_data *dev;
++ struct delayed_work release_urb_work;
+ struct urb *urb;
+ };
+
+@@ -87,6 +88,9 @@ struct dlfb_data {
+ #define MIN_RAW_PIX_BYTES 2
+ #define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
+
++#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */
++#define DL_DEFIO_WRITE_DISABLE (HZ*60) /* "disable" with long delay */
++
+ /* remove these once align.h patch is taken into kernel */
+ #define DL_ALIGN_UP(x, a) ALIGN(x, a)
+ #define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-minor-cleanups.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-minor-cleanups.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,101 @@
+From 3b7b31fa7df01576cc401dff512a6a84cb3753ed Mon Sep 17 00:00:00 2001
+From: Pavel Machek <pavel at ucw.cz>
+Date: Sat, 3 Apr 2010 07:00:37 +0200
+Subject: [PATCH] Staging: udlfb: minor cleanups
+
+This cleans up udlfb a tiny bit.
+
+Signed-off-by: Pavel Machek <pavel at ucw.cz>
+Cc: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/staging/udlfb/udlfb.c | 58 ++++++++++++++++++++--------------------
+ 1 files changed, 29 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index a78ade0..12444f2 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -58,17 +58,17 @@ static struct usb_device_id id_table[] = {
+ MODULE_DEVICE_TABLE(usb, id_table);
+
+ #ifndef CONFIG_FB_DEFERRED_IO
+-#warning message "kernel FB_DEFFERRED_IO option to support generic fbdev apps"
++#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 message "FB_SYS_* in kernel or module option to support fb console"
++#warning Please set CONFIG_FB_SYS_IMAGEBLIT option to support fb console
+ #endif
+ #endif
+
+ #ifndef CONFIG_FB_MODE_HELPERS
+-#warning message "kernel FB_MODE_HELPERS required. Expect build break"
++#warning CONFIG_FB_MODE_HELPERS required. Expect build break
+ #endif
+
+ /* dlfb keeps a list of urbs for efficient bulk transfers */
+@@ -366,32 +366,32 @@ static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
+ }
+
+ /*
+-Render a command stream for an encoded horizontal line segment of pixels.
+-
+-A command buffer holds several commands.
+-It always begins with a fresh command header
+-(the protocol doesn't require this, but we enforce it to allow
+-multiple buffers to be potentially encoded and sent in parallel).
+-A single command encodes one contiguous horizontal line of pixels
+-
+-The function relies on the client to do all allocation, so that
+-rendering can be done directly to output buffers (e.g. USB URBs).
+-The function fills the supplied command buffer, providing information
+-on where it left off, so the client may call in again with additional
+-buffers if the line will take several buffers to complete.
+-
+-A single command can transmit a maximum of 256 pixels,
+-regardless of the compression ratio (protocol design limit).
+-To the hardware, 0 for a size byte means 256
+-
+-Rather than 256 pixel commands which are either rl or raw encoded,
+-the rlx command simply assumes alternating raw and rl spans within one cmd.
+-This has a slightly larger header overhead, but produces more even results.
+-It also processes all data (read and write) in a single pass.
+-Performance benchmarks of common cases show it having just slightly better
+-compression than 256 pixel raw -or- rle commands, with similar CPU consumpion.
+-But for very rl friendly data, will compress not quite as well.
+-*/
++ * Render a command stream for an encoded horizontal line segment of pixels.
++ *
++ * A command buffer holds several commands.
++ * It always begins with a fresh command header
++ * (the protocol doesn't require this, but we enforce it to allow
++ * multiple buffers to be potentially encoded and sent in parallel).
++ * A single command encodes one contiguous horizontal line of pixels
++ *
++ * The function relies on the client to do all allocation, so that
++ * rendering can be done directly to output buffers (e.g. USB URBs).
++ * The function fills the supplied command buffer, providing information
++ * on where it left off, so the client may call in again with additional
++ * buffers if the line will take several buffers to complete.
++ *
++ * A single command can transmit a maximum of 256 pixels,
++ * regardless of the compression ratio (protocol design limit).
++ * To the hardware, 0 for a size byte means 256
++ *
++ * Rather than 256 pixel commands which are either rl or raw encoded,
++ * the rlx command simply assumes alternating raw and rl spans within one cmd.
++ * This has a slightly larger header overhead, but produces more even results.
++ * It also processes all data (read and write) in a single pass.
++ * Performance benchmarks of common cases show it having just slightly better
++ * compression than 256 pixel raw -or- rle commands, with similar CPU consumpion.
++ * But for very rl friendly data, will compress not quite as well.
++ */
+ static void dlfb_compress_hline(
+ const uint16_t **pixel_start_ptr,
+ const uint16_t *const pixel_end,
+--
+1.7.3.2
+
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-module-options.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-module-options.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,302 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:39 +0000 (-0700)
+Subject: staging: udlfb: add module options for console and fb_defio
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~674
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=d5ed54322e54d48e5fa66dff0086b79211f1cde7
+
+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 at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index b13869b..80a1e0e 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -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_info *info,
+
+ }
+
++#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 *info, unsigned int cmd,
+ 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 *info, int user)
+ {
+ 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 *info, int user)
+ 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);
+@@ -1341,30 +1395,6 @@ static ssize_t metrics_reset_store(struct device *fbdev,
+ 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,
+@@ -1379,60 +1409,9 @@ static struct device_attribute fb_device_attrs[] = {
+ __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,
+@@ -1559,6 +1538,8 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ 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 */
+
+@@ -1607,9 +1588,6 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+
+ /* 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);
+
+@@ -1889,6 +1867,12 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
+ 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 at unbit.it>, "
+ "Jaya Kumar <jayakumar.lkml at gmail.com>, "
+ "Bernie Thompson <bernie at plugable.com>");
+diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
+index d28e783..58d2af6 100644
+--- a/drivers/staging/udlfb/udlfb.h
++++ b/drivers/staging/udlfb/udlfb.h
+@@ -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;
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-remove-metrics_misc.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-remove-metrics_misc.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,146 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:15 +0000 (-0700)
+Subject: staging: udlfb: remove metrics_misc sysfs attribute
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~679
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f11f4bc027414bc7db5dde49c55b7149a627b591
+
+staging: udlfb: remove metrics_misc sysfs attribute
+
+Remove metrics_misc sysfs attribute
+
+Previously returned multiple values, which goes against sysfs guidelines.
+Had been used for debugging to figure out which of the multiple
+fbdev interfaces an app was using, but log file messages are sufficient.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index 0e03dd3..b027a1e 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -661,7 +661,6 @@ static void dlfb_ops_copyarea(struct fb_info *info,
+ dlfb_handle_damage(dev, area->dx, area->dy,
+ area->width, area->height, info->screen_base);
+ #endif
+- atomic_inc(&dev->copy_count);
+
+ }
+
+@@ -679,7 +678,6 @@ static void dlfb_ops_imageblit(struct fb_info *info,
+
+ #endif
+
+- atomic_inc(&dev->blit_count);
+ }
+
+ static void dlfb_ops_fillrect(struct fb_info *info,
+@@ -695,8 +693,6 @@ static void dlfb_ops_fillrect(struct fb_info *info,
+ rect->height, info->screen_base);
+ #endif
+
+- atomic_inc(&dev->fill_count);
+-
+ }
+
+ static void dlfb_get_edid(struct dlfb_data *dev)
+@@ -754,7 +750,6 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+
+ dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
+ info->screen_base);
+- atomic_inc(&dev->damage_count);
+ }
+
+ return 0;
+@@ -1088,29 +1083,6 @@ static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+ atomic_read(&dev->cpu_kcycles_used));
+ }
+
+-static ssize_t metrics_misc_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,
+- "Calls to\ndamage: %u\nblit: %u\n"
+- "defio faults: %u\ncopy: %u\n"
+- "fill: %u\n\n"
+- "active framebuffer clients: %d\n"
+- "urbs available %d(%d)\n"
+- "Shadow framebuffer in use? %s\n"
+- "Any lost pixels? %s\n",
+- atomic_read(&dev->damage_count),
+- atomic_read(&dev->blit_count),
+- atomic_read(&dev->defio_fault_count),
+- atomic_read(&dev->copy_count),
+- atomic_read(&dev->fill_count),
+- dev->fb_count,
+- dev->urbs.available, dev->urbs.limit_sem.count,
+- (dev->backing_buffer) ? "yes" : "no",
+- atomic_read(&dev->lost_pixels) ? "yes" : "no");
+-}
+-
+ static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *a,
+ char *buf, loff_t off, size_t count) {
+ struct device *fbdev = container_of(kobj, struct device, kobj);
+@@ -1144,11 +1116,6 @@ static ssize_t metrics_reset_store(struct device *fbdev,
+ atomic_set(&dev->bytes_identical, 0);
+ atomic_set(&dev->bytes_sent, 0);
+ atomic_set(&dev->cpu_kcycles_used, 0);
+- atomic_set(&dev->blit_count, 0);
+- atomic_set(&dev->copy_count, 0);
+- atomic_set(&dev->fill_count, 0);
+- atomic_set(&dev->defio_fault_count, 0);
+- atomic_set(&dev->damage_count, 0);
+
+ return count;
+ }
+@@ -1189,7 +1156,6 @@ static struct device_attribute fb_device_attrs[] = {
+ __ATTR_RO(metrics_bytes_identical),
+ __ATTR_RO(metrics_bytes_sent),
+ __ATTR_RO(metrics_cpu_kcycles_used),
+- __ATTR_RO(metrics_misc),
+ __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
+ __ATTR_RW(use_defio),
+ };
+@@ -1207,7 +1173,6 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
+ int bytes_sent = 0;
+ int bytes_identical = 0;
+ int bytes_rendered = 0;
+- int fault_count = 0;
+
+ if (!atomic_read(&dev->use_defio))
+ return;
+@@ -1228,7 +1193,6 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
+ &cmd, cur->index << PAGE_SHIFT,
+ PAGE_SIZE, &bytes_identical, &bytes_sent);
+ bytes_rendered += PAGE_SIZE;
+- fault_count++;
+ }
+
+ if (cmd > (char *) urb->transfer_buffer) {
+@@ -1239,7 +1203,6 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
+ } else
+ dlfb_urb_completion(urb);
+
+- atomic_add(fault_count, &dev->defio_fault_count);
+ atomic_add(bytes_sent, &dev->bytes_sent);
+ atomic_add(bytes_identical, &dev->bytes_identical);
+ atomic_add(bytes_rendered, &dev->bytes_rendered);
+diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
+index b07a693..f32a220 100644
+--- a/drivers/staging/udlfb/udlfb.h
++++ b/drivers/staging/udlfb/udlfb.h
+@@ -54,12 +54,6 @@ struct dlfb_data {
+ atomic_t bytes_identical; /* saved effort with backbuffer comparison */
+ atomic_t bytes_sent; /* to usb, after compression including overhead */
+ atomic_t cpu_kcycles_used; /* transpired during pixel processing */
+- /* interface usage metrics. Clients can call driver via several */
+- atomic_t blit_count;
+- atomic_t copy_count;
+- atomic_t fill_count;
+- atomic_t damage_count;
+- atomic_t defio_fault_count;
+ };
+
+ #define NR_USB_REQUEST_I2C_SUB_IO 0x02
Added: dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-revamp-reference-handling.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/udlfb/udlfb-revamp-reference-handling.patch Tue Nov 2 20:21:21 2010 (r16526)
@@ -0,0 +1,398 @@
+From: Bernie Thompson <bernie at plugable.com>
+Date: Sun, 5 Sep 2010 23:35:19 +0000 (-0700)
+Subject: staging: udlfb: revamp reference handling to insure successful shutdown
+X-Git-Tag: v2.6.37-rc1~60^2~3^2~678
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=33077b8d3042e01da61924973e372abe589ba297
+
+staging: udlfb: revamp reference handling to insure successful shutdown
+
+Revamp reference handling and synchronization for unload/shutdown
+
+Udlfb is a "virtual" framebuffer device that really exists on
+two separate stacks: at the bottom of the framebuffer interface,
+and on top of USB. During unload, there's no guarantee which
+one will tear down first. So reference counting must be solid
+to handle all possibilities and not access anything once its gone.
+
+Signed-off-by: Bernie Thompson <bernie at plugable.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
+index b027a1e..c9ac687 100644
+--- a/drivers/staging/udlfb/udlfb.c
++++ b/drivers/staging/udlfb/udlfb.c
+@@ -25,6 +25,8 @@
+ #include <linux/fb.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
++#include <linux/delay.h>
++
+
+ #include "udlfb.h"
+
+@@ -300,7 +302,6 @@ static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long page, pos;
+- struct dlfb_data *dev = info->par;
+
+ dl_notice("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
+
+@@ -785,6 +786,7 @@ dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
+ /*
+ * It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
++ * Assumes caller is holding info->lock (for open and release at least)
+ */
+ static int dlfb_ops_open(struct fb_info *info, int user)
+ {
+@@ -794,10 +796,14 @@ static int dlfb_ops_open(struct fb_info *info, int user)
+ * We could special case kernel mode clients (fbcon) here
+ */
+
+- mutex_lock(&dev->fb_open_lock);
++ /* If the USB device is gone, we don't accept new opens */
++ if (dev->virtualized)
++ return -ENODEV;
+
+ dev->fb_count++;
+
++ kref_get(&dev->kref);
++
+ #ifdef CONFIG_FB_DEFERRED_IO
+ if ((atomic_read(&dev->use_defio)) && (info->fbdefio == NULL)) {
+ /* enable defio */
+@@ -809,32 +815,6 @@ static int dlfb_ops_open(struct fb_info *info, int user)
+ dl_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
+ info->node, user, info, dev->fb_count);
+
+- mutex_unlock(&dev->fb_open_lock);
+-
+- return 0;
+-}
+-
+-static int dlfb_ops_release(struct fb_info *info, int user)
+-{
+- struct dlfb_data *dev = info->par;
+-
+- mutex_lock(&dev->fb_open_lock);
+-
+- dev->fb_count--;
+-
+-#ifdef CONFIG_FB_DEFERRED_IO
+- if ((dev->fb_count == 0) && (info->fbdefio)) {
+- fb_deferred_io_cleanup(info);
+- info->fbdefio = NULL;
+- info->fbops->fb_mmap = dlfb_ops_mmap;
+- }
+-#endif
+-
+- dl_notice("release /dev/fb%d user=%d count=%d\n",
+- info->node, user, dev->fb_count);
+-
+- mutex_unlock(&dev->fb_open_lock);
+-
+ return 0;
+ }
+
+@@ -843,25 +823,33 @@ static int dlfb_ops_release(struct fb_info *info, int user)
+ * and all references to our device instance (dlfb_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+-static void dlfb_delete(struct kref *kref)
++static void dlfb_free(struct kref *kref)
+ {
+ struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
+
++ /* this function will wait for all in-flight urbs to complete */
++ if (dev->urbs.count > 0)
++ dlfb_free_urb_list(dev);
++
+ if (dev->backing_buffer)
+ vfree(dev->backing_buffer);
+
+- mutex_destroy(&dev->fb_open_lock);
++ kfree(dev->edid);
++
++ dl_warn("freeing dlfb_data %p\n", dev);
+
+ kfree(dev);
+ }
+
+-/*
+- * Called by fbdev as last part of unregister_framebuffer() process
+- * No new clients can open connections. Deallocate everything fb_info.
+- */
+-static void dlfb_ops_destroy(struct fb_info *info)
++
++static void dlfb_free_framebuffer_work(struct work_struct *work)
+ {
+- struct dlfb_data *dev = info->par;
++ struct dlfb_data *dev = container_of(work, struct dlfb_data,
++ free_framebuffer_work.work);
++ struct fb_info *info = dev->info;
++ int node = info->node;
++
++ unregister_framebuffer(info);
+
+ if (info->cmap.len != 0)
+ fb_dealloc_cmap(&info->cmap);
+@@ -872,10 +860,45 @@ static void dlfb_ops_destroy(struct fb_info *info)
+
+ fb_destroy_modelist(&info->modelist);
+
++ dev->info = 0;
++
++ /* Assume info structure is freed after this point */
+ framebuffer_release(info);
+
+- /* ref taken before register_framebuffer() for dlfb_data clients */
+- kref_put(&dev->kref, dlfb_delete);
++ dl_warn("fb_info for /dev/fb%d has been freed\n", node);
++
++ /* ref taken in probe() as part of registering framebfufer */
++ kref_put(&dev->kref, dlfb_free);
++}
++
++/*
++ * Assumes caller is holding info->lock mutex (for open and release at least)
++ */
++static int dlfb_ops_release(struct fb_info *info, int user)
++{
++ struct dlfb_data *dev = info->par;
++
++ dev->fb_count--;
++
++ /* We can't free fb_info here - fbmem will touch it when we return */
++ if (dev->virtualized && (dev->fb_count == 0))
++ schedule_delayed_work(&dev->free_framebuffer_work, HZ);
++
++#ifdef CONFIG_FB_DEFERRED_IO
++ if ((dev->fb_count == 0) && (info->fbdefio)) {
++ fb_deferred_io_cleanup(info);
++ kfree(info->fbdefio);
++ info->fbdefio = NULL;
++ info->fbops->fb_mmap = dlfb_ops_mmap;
++ }
++#endif
++
++ dl_warn("released /dev/fb%d user=%d count=%d\n",
++ info->node, user, dev->fb_count);
++
++ kref_put(&dev->kref, dlfb_free);
++
++ return 0;
+ }
+
+ /*
+@@ -1243,13 +1266,12 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ {
+ struct usb_device *usbdev;
+ struct dlfb_data *dev;
+- struct fb_info *info;
++ struct fb_info *info = 0;
+ int videomemorysize;
+ int i;
+ unsigned char *videomemory;
+ int retval = -ENOMEM;
+ struct fb_var_screeninfo *var;
+- int registered = 0;
+ u16 *pix_framebuffer;
+
+ /* usb initialization */
+@@ -1276,8 +1298,6 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ goto error;
+ }
+
+- mutex_init(&dev->fb_open_lock);
+-
+ /* We don't register a new USB class. Our client interface is fbdev */
+
+ /* allocates framebuffer driver structure, not framebuffer memory */
+@@ -1287,6 +1307,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ dl_err("framebuffer_alloc failed\n");
+ goto error;
+ }
++
+ dev->info = info;
+ info->par = dev;
+ info->pseudo_palette = dev->pseudo_palette;
+@@ -1342,6 +1363,9 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ goto error;
+ }
+
++ INIT_DELAYED_WORK(&dev->free_framebuffer_work,
++ dlfb_free_framebuffer_work);
++
+ /* ready to begin using device */
+
+ #ifdef CONFIG_FB_DEFERRED_IO
+@@ -1366,7 +1390,6 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+ dl_err("register_framebuffer failed %d\n", retval);
+ goto error;
+ }
+- registered = 1;
+
+ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+ device_create_file(info->dev, &fb_device_attrs[i]);
+@@ -1382,15 +1405,25 @@ static int dlfb_usb_probe(struct usb_interface *interface,
+
+ error:
+ if (dev) {
+- if (registered) {
+- unregister_framebuffer(info);
+- dlfb_ops_destroy(info);
+- } else
+- kref_put(&dev->kref, dlfb_delete);
+
+- if (dev->urbs.count > 0)
+- dlfb_free_urb_list(dev);
+- kref_put(&dev->kref, dlfb_delete); /* last ref from kref_init */
++ if (info) {
++ if (info->cmap.len != 0)
++ fb_dealloc_cmap(&info->cmap);
++ if (info->monspecs.modedb)
++ fb_destroy_modedb(info->monspecs.modedb);
++ if (info->screen_base)
++ vfree(info->screen_base);
++
++ fb_destroy_modelist(&info->modelist);
++
++ framebuffer_release(info);
++ }
++
++ if (dev->backing_buffer)
++ vfree(dev->backing_buffer);
++
++ kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
++ kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
+
+ /* dev has been deallocated. Do not dereference */
+ }
+@@ -1407,27 +1440,27 @@ static void dlfb_usb_disconnect(struct usb_interface *interface)
+ dev = usb_get_intfdata(interface);
+ info = dev->info;
+
+- /* when non-active we'll update virtual framebuffer, but no new urbs */
+- atomic_set(&dev->usb_active, 0);
++ dl_info("USB disconnect starting\n");
+
+- usb_set_intfdata(interface, NULL);
++ /* we virtualize until all fb clients release. Then we free */
++ dev->virtualized = true;
++
++ /* When non-active we'll update virtual framebuffer, but no new urbs */
++ atomic_set(&dev->usb_active, 0);
+
++ /* remove udlfb's sysfs interfaces */
+ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+ device_remove_file(info->dev, &fb_device_attrs[i]);
+-
+ device_remove_bin_file(info->dev, &edid_attr);
+
+- /* this function will wait for all in-flight urbs to complete */
+- dlfb_free_urb_list(dev);
++ usb_set_intfdata(interface, NULL);
+
+- if (info) {
+- dl_notice("Detaching /dev/fb%d\n", info->node);
+- unregister_framebuffer(info);
+- dlfb_ops_destroy(info);
+- }
++ /* if clients still have us open, will be freed on last close */
++ if (dev->fb_count == 0)
++ schedule_delayed_work(&dev->free_framebuffer_work, 0);
+
+ /* release reference taken by kref_init in probe() */
+- kref_put(&dev->kref, dlfb_delete);
++ kref_put(&dev->kref, dlfb_free);
+
+ /* consider dlfb_data freed */
+
+@@ -1449,8 +1482,6 @@ static int __init dlfb_module_init(void)
+ if (res)
+ err("usb_register failed. Error number %d", res);
+
+- printk(KERN_INFO "VMODES initialized\n");
+-
+ return res;
+ }
+
+@@ -1502,12 +1533,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
+
+ /* keep waiting and freeing, until we've got 'em all */
+ while (count--) {
+- /* Timeout means a memory leak and/or fault */
+- ret = down_timeout(&dev->urbs.limit_sem, FREE_URB_TIMEOUT);
+- if (ret) {
+- BUG_ON(ret);
++
++ /* Getting interrupted means a leak, but ok at shutdown*/
++ ret = down_interruptible(&dev->urbs.limit_sem);
++ if (ret)
+ break;
+- }
++
+ spin_lock_irqsave(&dev->urbs.lock, flags);
+
+ node = dev->urbs.list.next; /* have reserved one with sem */
+@@ -1525,8 +1556,6 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
+ kfree(node);
+ }
+
+- kref_put(&dev->kref, dlfb_delete);
+-
+ }
+
+ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+@@ -1576,8 +1605,6 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+ dev->urbs.count = i;
+ dev->urbs.available = i;
+
+- kref_get(&dev->kref); /* released in free_render_urbs() */
+-
+ dl_notice("allocated %d %d byte urbs\n", i, (int) size);
+
+ return i;
+diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
+index f32a220..7c46477 100644
+--- a/drivers/staging/udlfb/udlfb.h
++++ b/drivers/staging/udlfb/udlfb.h
+@@ -38,9 +38,9 @@ struct dlfb_data {
+ struct urb_list urbs;
+ struct kref kref;
+ char *backing_buffer;
+- struct delayed_work deferred_work;
+- struct mutex fb_open_lock;
+ int fb_count;
++ bool virtualized; /* true when physical usb device not present */
++ 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 */
+@@ -89,12 +89,20 @@ struct dlfb_data {
+ /* remove once this gets added to sysfs.h */
+ #define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
+
++/*
++ * udlfb is both a usb device, and a framebuffer device.
++ * They may exist at the same time, but during various stages
++ * inactivity, teardown, or "virtual" operation, only one or the
++ * other will exist (one will outlive the other). So we can't
++ * call the dev_*() macros, because we don't have a stable dev object.
++ */
+ #define dl_err(format, arg...) \
+- dev_err(dev->gdev, "dlfb: " format, ## arg)
++ pr_err("udlfb: " format, ## arg)
+ #define dl_warn(format, arg...) \
+- dev_warn(dev->gdev, "dlfb: " format, ## arg)
++ pr_warning("udlfb: " format, ## arg)
+ #define dl_notice(format, arg...) \
+- dev_notice(dev->gdev, "dlfb: " format, ## arg)
++ pr_notice("udlfb: " format, ## arg)
+ #define dl_info(format, arg...) \
+- dev_info(dev->gdev, "dlfb: " format, ## arg)
++ pr_info("udlfb: " format, ## arg)
++
+ #endif
Modified: dists/sid/linux-2.6/debian/patches/series/28
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/28 Tue Nov 2 16:36:34 2010 (r16525)
+++ dists/sid/linux-2.6/debian/patches/series/28 Tue Nov 2 20:21:21 2010 (r16526)
@@ -2,3 +2,16 @@
+ bugfix/all/drm-i915-set-DIDL-using-the-ACPI-video-output-device.patch
+ bugfix/all/drm-ttm-Clear-the-ghost-cpu_writers-flag-on-ttm_buff.patch
+ bugfix/all/drm-nouveau-fix-race-condition-when-under-memory-pre.patch
++ features/all/udlfb/udlfb-add-slab.patch
++ features/all/udlfb/udlfb-minor-cleanups.patch
++ features/all/udlfb/udlfb-coding-style.patch
++ features/all/udlfb/udlfb-fbdev-char.patch
++ features/all/udlfb/udlfb-add-dpms.patch
++ features/all/udlfb/udlfb-remove-metrics_misc.patch
++ features/all/udlfb/udlfb-revamp-reference-handling.patch
++ features/all/udlfb/udlfb-enhance-edid.patch
++ features/all/udlfb/udlfb-big-endian-fix.patch
++ features/all/udlfb/udlfb-backup-edid-write.patch
++ features/all/udlfb/udlfb-module-options.patch
++ features/all/udlfb/udlfb-fix-incorrect-fb_defio-implementation.patch
++ features/all/udlfb/udlfb-checkpatch-style.patch
More information about the Kernel-svn-changes
mailing list