diff --git a/kernel.spec b/kernel.spec index bf55811b5..273631fe8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -87,7 +87,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 1 # The git snapshot level -%define gitrev 5 +%define gitrev 6 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -741,6 +741,8 @@ Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch Patch21091: kmemleak.patch +Patch21092: udlfb-remove-sysfs-framebuffer-device-with-USB-disconnect.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1432,6 +1434,8 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch ApplyPatch kmemleak.patch +ApplyPatch udlfb-remove-sysfs-framebuffer-device-with-USB-disconnect.patch + #rhbz 783211 ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch @@ -2281,6 +2285,12 @@ fi # ||----w | # || || %changelog +* Mon Jan 30 2012 Josh Boyer - 3.3.0-0.rc1.git6.1 +- Linux 3.3-rc1-git6 (upstream 6bc2b95ee602659c1be6fac0f6aadeb0c5c29a5d) +- Add patch from Kay Sievers for udlfb device removal +- utrace patch to allow calling internal functions from atomic context from + Oleg Nesterov + * Mon Jan 30 2012 John W. Linville - ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix diff --git a/udlfb-remove-sysfs-framebuffer-device-with-USB-disconnect.patch b/udlfb-remove-sysfs-framebuffer-device-with-USB-disconnect.patch new file mode 100644 index 000000000..c304713a1 --- /dev/null +++ b/udlfb-remove-sysfs-framebuffer-device-with-USB-disconnect.patch @@ -0,0 +1,118 @@ +From 92a9c19a89af2ca219fbb040a0059f414a4b7223 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Sat, 28 Jan 2012 19:57:46 +0000 +Subject: [PATCH] udlfb: remove sysfs framebuffer device with USB + .disconnect() + +The USB graphics card driver delays the unregistering of the framebuffer +device to a workqueue, which breaks the userspace visible remove uevent +sequence. Recent userspace tools started to support USB graphics card +hotplug out-of-the-box and rely on proper events sent by the kernel. + +The framebuffer device is a direct child of the USB interface which is +removed immediately after the USB .disconnect() callback. But the fb device +in /sys stays around until its final cleanup, at a time where all the parent +devices have been removed already. + +To work around that, we remove the sysfs fb device directly in the USB +.disconnect() callback and leave only the cleanup of the internal fb +data to the delayed work. + +Before: + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb) + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb) + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb0 (graphics) + remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb) + remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb) + remove /2-1.2:1.0/graphics/fb0 (graphics) + +After: + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb) + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb) + add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics) + remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics) + remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb) + remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb) + +Cc: stable@vger.kernel.org +Tested-by: Bernie Thompson +Acked-by: Bernie Thompson +Signed-off-by: Kay Sievers +Signed-off-by: Florian Tobias Schandinat +--- + drivers/video/fbmem.c | 18 +++++++++++++++++- + drivers/video/udlfb.c | 2 +- + include/linux/fb.h | 1 + + 3 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c +index ac9141b..c6ce416 100644 +--- a/drivers/video/fbmem.c ++++ b/drivers/video/fbmem.c +@@ -1665,6 +1665,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) + if (ret) + return -EINVAL; + ++ unlink_framebuffer(fb_info); + if (fb_info->pixmap.addr && + (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) + kfree(fb_info->pixmap.addr); +@@ -1672,7 +1673,6 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) + registered_fb[i] = NULL; + num_registered_fb--; + fb_cleanup_device(fb_info); +- device_destroy(fb_class, MKDEV(FB_MAJOR, i)); + event.info = fb_info; + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + +@@ -1681,6 +1681,22 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) + return 0; + } + ++int unlink_framebuffer(struct fb_info *fb_info) ++{ ++ int i; ++ ++ i = fb_info->node; ++ if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) ++ return -EINVAL; ++ ++ if (fb_info->dev) { ++ device_destroy(fb_class, MKDEV(FB_MAJOR, i)); ++ fb_info->dev = NULL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(unlink_framebuffer); ++ + void remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) + { +diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c +index a197731..a40c05e 100644 +--- a/drivers/video/udlfb.c ++++ b/drivers/video/udlfb.c +@@ -1739,7 +1739,7 @@ static void dlfb_usb_disconnect(struct usb_interface *interface) + 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); +- ++ unlink_framebuffer(info); + usb_set_intfdata(interface, NULL); + + /* if clients still have us open, will be freed on last close */ +diff --git a/include/linux/fb.h b/include/linux/fb.h +index c18122f..a395b8c 100644 +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -1003,6 +1003,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, + /* drivers/video/fbmem.c */ + extern int register_framebuffer(struct fb_info *fb_info); + extern int unregister_framebuffer(struct fb_info *fb_info); ++extern int unlink_framebuffer(struct fb_info *fb_info); + extern void remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary); + extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); +-- +1.7.6.5 + diff --git a/utrace.patch b/utrace.patch index 0e34971ca..556188a88 100644 --- a/utrace.patch +++ b/utrace.patch @@ -4683,3 +4683,73 @@ index 0000000..c817a46 + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} +Add the new UTRACE_ATTACH_ATOMIC flag for utrace_attach_task(). +If it is set, UTRACE_ATTACH_CREATE uses GFP_ATOMIC for memory +allocations and thus it can be used in atomic context. + +Suggested-by: Mark Wielaard +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 1 + + kernel/utrace.c | 12 ++++++++---- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index f37373b..46959af 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -317,6 +317,7 @@ static inline enum utrace_syscall_action utrace_syscall_action(u32 action) + #define UTRACE_ATTACH_MATCH_MASK 0x000f + #define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ + #define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ ++#define UTRACE_ATTACH_ATOMIC 0x0040 /* For _CREATE, don't sleep */ + + /** + * struct utrace_engine - per-engine structure +diff --git a/kernel/utrace.c b/kernel/utrace.c +index c817a46..a169e1b 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -113,9 +113,9 @@ void task_utrace_unlock(struct task_struct *task) + * + * This returns false only in case of a memory allocation failure. + */ +-static bool utrace_task_alloc(struct task_struct *task) ++static bool utrace_task_alloc(struct task_struct *task, gfp_t gfp_flags) + { +- struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); ++ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, gfp_flags); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); +@@ -295,6 +295,7 @@ struct utrace_engine *utrace_attach_task( + { + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; ++ gfp_t gfp_flags; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { +@@ -317,13 +318,16 @@ struct utrace_engine *utrace_attach_task( + */ + return ERR_PTR(-EPERM); + ++ gfp_flags = (flags & UTRACE_ATTACH_ATOMIC) ++ ? GFP_ATOMIC : GFP_KERNEL; ++ + if (!utrace) { +- if (unlikely(!utrace_task_alloc(target))) ++ if (unlikely(!utrace_task_alloc(target, gfp_flags))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + +- engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); ++ engine = kmem_cache_alloc(utrace_engine_cachep, gfp_flags); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + +-- +1.5.5.1 + +