From 68a958a915ca912b8ce71b9eea7445996f6e681e Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 8 Oct 2018 12:57:34 +0200 Subject: udlfb: handle unplug properly The udlfb driver maintained an open count and cleaned up itself when the count reached zero. But the console is also counted in the reference count - so, if the user unplugged the device, the open count would not drop to zero and the driver stayed loaded with console attached. If the user re-plugged the adapter, it would create a device /dev/fb1, show green screen and the access to the console would be lost. The framebuffer subsystem has reference counting on its own - in order to fix the unplug bug, we rely the framebuffer reference counting. When the user unplugs the adapter, we call unregister_framebuffer unconditionally. unregister_framebuffer will unbind the console, wait until all users stop using the framebuffer and then call the fb_destroy method. The fb_destroy cleans up the USB driver. This patch makes the following changes: * Drop dlfb->kref and rely on implicit framebuffer reference counting instead. * dlfb_usb_disconnect calls unregister_framebuffer, the rest of driver cleanup is done in the function dlfb_ops_destroy. dlfb_ops_destroy will be called by the framebuffer subsystem when no processes have the framebuffer open or mapped. * We don't use workqueue during initialization, but initialize directly from dlfb_usb_probe. The workqueue could race with dlfb_usb_disconnect and this racing would produce various kinds of memory corruption. * We use usb_get_dev and usb_put_dev to make sure that the USB subsystem doesn't free the device under us. Signed-off-by: Mikulas Patocka cc: Dave Airlie Cc: Bernie Thompson , Cc: Ladislav Michl Signed-off-by: Bartlomiej Zolnierkiewicz --- include/video/udlfb.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/video') diff --git a/include/video/udlfb.h b/include/video/udlfb.h index 3abd327bada6..7d09e54ae54e 100644 --- a/include/video/udlfb.h +++ b/include/video/udlfb.h @@ -36,12 +36,9 @@ struct dlfb_data { struct usb_device *udev; struct fb_info *info; struct urb_list urbs; - struct kref kref; char *backing_buffer; int fb_count; bool virtualized; /* true when physical usb device not present */ - struct delayed_work init_framebuffer_work; - 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 */ char *edid; /* null until we read edid from hw or get from sysfs */ -- cgit v1.2.3-59-g8ed1b