Loading MAINTAINERS +9 −0 Original line number Original line Diff line number Diff line Loading @@ -2231,6 +2231,15 @@ F: Documentation/filesystems/quota.txt F: fs/quota/ F: fs/quota/ F: include/linux/quota*.h F: include/linux/quota*.h DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB) M: Bernie Thompson <bernie@plugable.com> L: linux-fbdev@vger.kernel.org S: Maintained W: http://plugable.com/category/projects/udlfb/ F: drivers/video/udlfb.c F: include/video/udlfb.h F: Documentation/fb/udlfb.txt DISTRIBUTED LOCK MANAGER (DLM) DISTRIBUTED LOCK MANAGER (DLM) M: Christine Caulfield <ccaulfie@redhat.com> M: Christine Caulfield <ccaulfie@redhat.com> M: David Teigland <teigland@redhat.com> M: David Teigland <teigland@redhat.com> Loading drivers/video/udlfb.c +95 −68 Original line number Original line Diff line number Diff line Loading @@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, id_table); static bool console = 1; /* Allow fbcon to open framebuffer */ static bool console = 1; /* Allow fbcon to open framebuffer */ static bool fb_defio = 1; /* Detect mmap writes using page faults */ static bool fb_defio = 1; /* Detect mmap writes using page faults */ static bool shadow = 1; /* Optionally disable shadow framebuffer */ static bool shadow = 1; /* Optionally disable shadow framebuffer */ static int pixel_limit; /* Optionally force a pixel resolution limit */ /* dlfb keeps a list of urbs for efficient bulk transfers */ /* dlfb keeps a list of urbs for efficient bulk transfers */ static void dlfb_urb_completion(struct urb *urb); static void dlfb_urb_completion(struct urb *urb); Loading Loading @@ -918,10 +919,6 @@ static void dlfb_free(struct kref *kref) { { struct dlfb_data *dev = container_of(kref, struct dlfb_data, 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) if (dev->backing_buffer) vfree(dev->backing_buffer); vfree(dev->backing_buffer); Loading @@ -940,11 +937,11 @@ static void dlfb_release_urb_work(struct work_struct *work) up(&unode->dev->urbs.limit_sem); up(&unode->dev->urbs.limit_sem); } } static void dlfb_free_framebuffer_work(struct work_struct *work) static void dlfb_free_framebuffer(struct dlfb_data *dev) { { struct dlfb_data *dev = container_of(work, struct dlfb_data, free_framebuffer_work.work); struct fb_info *info = dev->info; struct fb_info *info = dev->info; if (info) { int node = info->node; int node = info->node; unregister_framebuffer(info); unregister_framebuffer(info); Loading @@ -958,17 +955,24 @@ static void dlfb_free_framebuffer_work(struct work_struct *work) fb_destroy_modelist(&info->modelist); fb_destroy_modelist(&info->modelist); dev->info = 0; dev->info = NULL; /* Assume info structure is freed after this point */ /* Assume info structure is freed after this point */ framebuffer_release(info); framebuffer_release(info); pr_warn("fb_info for /dev/fb%d has been freed\n", node); pr_warn("fb_info for /dev/fb%d has been freed\n", node); } /* ref taken in probe() as part of registering framebfufer */ /* ref taken in probe() as part of registering framebfufer */ kref_put(&dev->kref, dlfb_free); kref_put(&dev->kref, dlfb_free); } } static void dlfb_free_framebuffer_work(struct work_struct *work) { struct dlfb_data *dev = container_of(work, struct dlfb_data, free_framebuffer_work.work); dlfb_free_framebuffer(dev); } /* /* * Assumes caller is holding info->lock mutex (for open and release at least) * Assumes caller is holding info->lock mutex (for open and release at least) */ */ Loading Loading @@ -1012,7 +1016,8 @@ static int dlfb_is_valid_mode(struct fb_videomode *mode, return 0; return 0; } } pr_info("%dx%d valid mode\n", mode->xres, mode->yres); pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres, mode->refresh); return 1; return 1; } } Loading Loading @@ -1537,7 +1542,7 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, u8 length; u8 length; u16 key; u16 key; key = *((u16 *) desc); key = le16_to_cpu(*((u16 *) desc)); desc += sizeof(u16); desc += sizeof(u16); length = *desc; length = *desc; desc++; desc++; Loading Loading @@ -1570,14 +1575,15 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, kfree(buf); kfree(buf); return true; return true; } } static void dlfb_init_framebuffer_work(struct work_struct *work); static int dlfb_usb_probe(struct usb_interface *interface, static int dlfb_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) const struct usb_device_id *id) { { struct usb_device *usbdev; struct usb_device *usbdev; struct dlfb_data *dev = 0; struct dlfb_data *dev = 0; struct fb_info *info = 0; int retval = -ENOMEM; int retval = -ENOMEM; int i; /* usb initialization */ /* usb initialization */ Loading @@ -1589,9 +1595,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, goto error; goto error; } } /* 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_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ dev->udev = usbdev; dev->udev = usbdev; dev->gdev = &usbdev->dev; /* our generic struct device * */ dev->gdev = &usbdev->dev; /* our generic struct device * */ Loading @@ -1613,16 +1617,53 @@ static int dlfb_usb_probe(struct usb_interface *interface, goto error; goto error; } } if (pixel_limit) { pr_warn("DL chip limit of %d overriden" " by module param to %d\n", dev->sku_pixel_limit, pixel_limit); dev->sku_pixel_limit = pixel_limit; } if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { retval = -ENOMEM; retval = -ENOMEM; pr_err("dlfb_alloc_urb_list failed\n"); pr_err("dlfb_alloc_urb_list failed\n"); goto error; goto error; } } kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ /* We don't register a new USB class. Our client interface is fbdev */ /* We don't register a new USB class. Our client interface is fbdev */ /* Workitem keep things fast & simple during USB enumeration */ INIT_DELAYED_WORK(&dev->init_framebuffer_work, dlfb_init_framebuffer_work); schedule_delayed_work(&dev->init_framebuffer_work, 0); return 0; error: if (dev) { 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 */ } return retval; } static void dlfb_init_framebuffer_work(struct work_struct *work) { struct dlfb_data *dev = container_of(work, struct dlfb_data, init_framebuffer_work.work); struct fb_info *info; int retval; int i; /* allocates framebuffer driver structure, not framebuffer memory */ /* allocates framebuffer driver structure, not framebuffer memory */ info = framebuffer_alloc(0, &interface->dev); info = framebuffer_alloc(0, dev->gdev); if (!info) { if (!info) { retval = -ENOMEM; retval = -ENOMEM; pr_err("framebuffer_alloc failed\n"); pr_err("framebuffer_alloc failed\n"); Loading Loading @@ -1668,15 +1709,13 @@ static int dlfb_usb_probe(struct usb_interface *interface, for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { retval = device_create_file(info->dev, &fb_device_attrs[i]); retval = device_create_file(info->dev, &fb_device_attrs[i]); if (retval) { if (retval) { pr_err("device_create_file failed %d\n", retval); pr_warn("device_create_file failed %d\n", retval); goto err_del_attrs; } } } } retval = device_create_bin_file(info->dev, &edid_attr); retval = device_create_bin_file(info->dev, &edid_attr); if (retval) { if (retval) { pr_err("device_create_bin_file failed %d\n", retval); pr_warn("device_create_bin_file failed %d\n", retval); goto err_del_attrs; } } pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." Loading @@ -1684,38 +1723,10 @@ static int dlfb_usb_probe(struct usb_interface *interface, info->var.xres, info->var.yres, info->var.xres, info->var.yres, ((dev->backing_buffer) ? ((dev->backing_buffer) ? info->fix.smem_len * 2 : info->fix.smem_len) >> 10); info->fix.smem_len * 2 : info->fix.smem_len) >> 10); return 0; return; err_del_attrs: for (i -= 1; i >= 0; i--) device_remove_file(info->dev, &fb_device_attrs[i]); error: error: if (dev) { dlfb_free_framebuffer(dev); 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 */ } return retval; } } static void dlfb_usb_disconnect(struct usb_interface *interface) static void dlfb_usb_disconnect(struct usb_interface *interface) Loading @@ -1735,12 +1746,24 @@ static void dlfb_usb_disconnect(struct usb_interface *interface) /* When non-active we'll update virtual framebuffer, but no new urbs */ /* When non-active we'll update virtual framebuffer, but no new urbs */ atomic_set(&dev->usb_active, 0); atomic_set(&dev->usb_active, 0); /* this function will wait for all in-flight urbs to complete */ dlfb_free_urb_list(dev); if (info) { /* remove udlfb's sysfs interfaces */ /* remove udlfb's sysfs interfaces */ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_bin_file(info->dev, &edid_attr); device_remove_bin_file(info->dev, &edid_attr); /* it's safe to uncomment next line if your kernel doesn't yet have this function exported */ unlink_framebuffer(info); unlink_framebuffer(info); } usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL); dev->udev = NULL; dev->gdev = NULL; /* if clients still have us open, will be freed on last close */ /* if clients still have us open, will be freed on last close */ if (dev->fb_count == 0) if (dev->fb_count == 0) Loading Loading @@ -1806,12 +1829,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev) int ret; int ret; unsigned long flags; unsigned long flags; pr_notice("Waiting for completes and freeing all render urbs\n"); pr_notice("Freeing all render urbs\n"); /* keep waiting and freeing, until we've got 'em all */ /* keep waiting and freeing, until we've got 'em all */ while (count--) { while (count--) { /* Getting interrupted means a leak, but ok at shutdown*/ /* Getting interrupted means a leak, but ok at disconnect */ ret = down_interruptible(&dev->urbs.limit_sem); ret = down_interruptible(&dev->urbs.limit_sem); if (ret) if (ret) break; break; Loading @@ -1833,6 +1856,7 @@ static void dlfb_free_urb_list(struct dlfb_data *dev) kfree(node); kfree(node); } } dev->urbs.count = 0; } } static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) Loading Loading @@ -1948,6 +1972,9 @@ MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes"); module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)"); MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " "Jaya Kumar <jayakumar.lkml@gmail.com>, " "Jaya Kumar <jayakumar.lkml@gmail.com>, " "Bernie Thompson <bernie@plugable.com>"); "Bernie Thompson <bernie@plugable.com>"); Loading include/video/udlfb.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ struct dlfb_data { char *backing_buffer; char *backing_buffer; int fb_count; int fb_count; bool virtualized; /* true when physical usb device not present */ bool virtualized; /* true when physical usb device not present */ struct delayed_work init_framebuffer_work; struct delayed_work free_framebuffer_work; struct delayed_work free_framebuffer_work; atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 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 lost_pixels; /* 1 = a render op failed. Need screen refresh */ Loading Loading
MAINTAINERS +9 −0 Original line number Original line Diff line number Diff line Loading @@ -2231,6 +2231,15 @@ F: Documentation/filesystems/quota.txt F: fs/quota/ F: fs/quota/ F: include/linux/quota*.h F: include/linux/quota*.h DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB) M: Bernie Thompson <bernie@plugable.com> L: linux-fbdev@vger.kernel.org S: Maintained W: http://plugable.com/category/projects/udlfb/ F: drivers/video/udlfb.c F: include/video/udlfb.h F: Documentation/fb/udlfb.txt DISTRIBUTED LOCK MANAGER (DLM) DISTRIBUTED LOCK MANAGER (DLM) M: Christine Caulfield <ccaulfie@redhat.com> M: Christine Caulfield <ccaulfie@redhat.com> M: David Teigland <teigland@redhat.com> M: David Teigland <teigland@redhat.com> Loading
drivers/video/udlfb.c +95 −68 Original line number Original line Diff line number Diff line Loading @@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, id_table); static bool console = 1; /* Allow fbcon to open framebuffer */ static bool console = 1; /* Allow fbcon to open framebuffer */ static bool fb_defio = 1; /* Detect mmap writes using page faults */ static bool fb_defio = 1; /* Detect mmap writes using page faults */ static bool shadow = 1; /* Optionally disable shadow framebuffer */ static bool shadow = 1; /* Optionally disable shadow framebuffer */ static int pixel_limit; /* Optionally force a pixel resolution limit */ /* dlfb keeps a list of urbs for efficient bulk transfers */ /* dlfb keeps a list of urbs for efficient bulk transfers */ static void dlfb_urb_completion(struct urb *urb); static void dlfb_urb_completion(struct urb *urb); Loading Loading @@ -918,10 +919,6 @@ static void dlfb_free(struct kref *kref) { { struct dlfb_data *dev = container_of(kref, struct dlfb_data, 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) if (dev->backing_buffer) vfree(dev->backing_buffer); vfree(dev->backing_buffer); Loading @@ -940,11 +937,11 @@ static void dlfb_release_urb_work(struct work_struct *work) up(&unode->dev->urbs.limit_sem); up(&unode->dev->urbs.limit_sem); } } static void dlfb_free_framebuffer_work(struct work_struct *work) static void dlfb_free_framebuffer(struct dlfb_data *dev) { { struct dlfb_data *dev = container_of(work, struct dlfb_data, free_framebuffer_work.work); struct fb_info *info = dev->info; struct fb_info *info = dev->info; if (info) { int node = info->node; int node = info->node; unregister_framebuffer(info); unregister_framebuffer(info); Loading @@ -958,17 +955,24 @@ static void dlfb_free_framebuffer_work(struct work_struct *work) fb_destroy_modelist(&info->modelist); fb_destroy_modelist(&info->modelist); dev->info = 0; dev->info = NULL; /* Assume info structure is freed after this point */ /* Assume info structure is freed after this point */ framebuffer_release(info); framebuffer_release(info); pr_warn("fb_info for /dev/fb%d has been freed\n", node); pr_warn("fb_info for /dev/fb%d has been freed\n", node); } /* ref taken in probe() as part of registering framebfufer */ /* ref taken in probe() as part of registering framebfufer */ kref_put(&dev->kref, dlfb_free); kref_put(&dev->kref, dlfb_free); } } static void dlfb_free_framebuffer_work(struct work_struct *work) { struct dlfb_data *dev = container_of(work, struct dlfb_data, free_framebuffer_work.work); dlfb_free_framebuffer(dev); } /* /* * Assumes caller is holding info->lock mutex (for open and release at least) * Assumes caller is holding info->lock mutex (for open and release at least) */ */ Loading Loading @@ -1012,7 +1016,8 @@ static int dlfb_is_valid_mode(struct fb_videomode *mode, return 0; return 0; } } pr_info("%dx%d valid mode\n", mode->xres, mode->yres); pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres, mode->refresh); return 1; return 1; } } Loading Loading @@ -1537,7 +1542,7 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, u8 length; u8 length; u16 key; u16 key; key = *((u16 *) desc); key = le16_to_cpu(*((u16 *) desc)); desc += sizeof(u16); desc += sizeof(u16); length = *desc; length = *desc; desc++; desc++; Loading Loading @@ -1570,14 +1575,15 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, kfree(buf); kfree(buf); return true; return true; } } static void dlfb_init_framebuffer_work(struct work_struct *work); static int dlfb_usb_probe(struct usb_interface *interface, static int dlfb_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) const struct usb_device_id *id) { { struct usb_device *usbdev; struct usb_device *usbdev; struct dlfb_data *dev = 0; struct dlfb_data *dev = 0; struct fb_info *info = 0; int retval = -ENOMEM; int retval = -ENOMEM; int i; /* usb initialization */ /* usb initialization */ Loading @@ -1589,9 +1595,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, goto error; goto error; } } /* 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_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ dev->udev = usbdev; dev->udev = usbdev; dev->gdev = &usbdev->dev; /* our generic struct device * */ dev->gdev = &usbdev->dev; /* our generic struct device * */ Loading @@ -1613,16 +1617,53 @@ static int dlfb_usb_probe(struct usb_interface *interface, goto error; goto error; } } if (pixel_limit) { pr_warn("DL chip limit of %d overriden" " by module param to %d\n", dev->sku_pixel_limit, pixel_limit); dev->sku_pixel_limit = pixel_limit; } if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { retval = -ENOMEM; retval = -ENOMEM; pr_err("dlfb_alloc_urb_list failed\n"); pr_err("dlfb_alloc_urb_list failed\n"); goto error; goto error; } } kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ /* We don't register a new USB class. Our client interface is fbdev */ /* We don't register a new USB class. Our client interface is fbdev */ /* Workitem keep things fast & simple during USB enumeration */ INIT_DELAYED_WORK(&dev->init_framebuffer_work, dlfb_init_framebuffer_work); schedule_delayed_work(&dev->init_framebuffer_work, 0); return 0; error: if (dev) { 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 */ } return retval; } static void dlfb_init_framebuffer_work(struct work_struct *work) { struct dlfb_data *dev = container_of(work, struct dlfb_data, init_framebuffer_work.work); struct fb_info *info; int retval; int i; /* allocates framebuffer driver structure, not framebuffer memory */ /* allocates framebuffer driver structure, not framebuffer memory */ info = framebuffer_alloc(0, &interface->dev); info = framebuffer_alloc(0, dev->gdev); if (!info) { if (!info) { retval = -ENOMEM; retval = -ENOMEM; pr_err("framebuffer_alloc failed\n"); pr_err("framebuffer_alloc failed\n"); Loading Loading @@ -1668,15 +1709,13 @@ static int dlfb_usb_probe(struct usb_interface *interface, for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { retval = device_create_file(info->dev, &fb_device_attrs[i]); retval = device_create_file(info->dev, &fb_device_attrs[i]); if (retval) { if (retval) { pr_err("device_create_file failed %d\n", retval); pr_warn("device_create_file failed %d\n", retval); goto err_del_attrs; } } } } retval = device_create_bin_file(info->dev, &edid_attr); retval = device_create_bin_file(info->dev, &edid_attr); if (retval) { if (retval) { pr_err("device_create_bin_file failed %d\n", retval); pr_warn("device_create_bin_file failed %d\n", retval); goto err_del_attrs; } } pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." Loading @@ -1684,38 +1723,10 @@ static int dlfb_usb_probe(struct usb_interface *interface, info->var.xres, info->var.yres, info->var.xres, info->var.yres, ((dev->backing_buffer) ? ((dev->backing_buffer) ? info->fix.smem_len * 2 : info->fix.smem_len) >> 10); info->fix.smem_len * 2 : info->fix.smem_len) >> 10); return 0; return; err_del_attrs: for (i -= 1; i >= 0; i--) device_remove_file(info->dev, &fb_device_attrs[i]); error: error: if (dev) { dlfb_free_framebuffer(dev); 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 */ } return retval; } } static void dlfb_usb_disconnect(struct usb_interface *interface) static void dlfb_usb_disconnect(struct usb_interface *interface) Loading @@ -1735,12 +1746,24 @@ static void dlfb_usb_disconnect(struct usb_interface *interface) /* When non-active we'll update virtual framebuffer, but no new urbs */ /* When non-active we'll update virtual framebuffer, but no new urbs */ atomic_set(&dev->usb_active, 0); atomic_set(&dev->usb_active, 0); /* this function will wait for all in-flight urbs to complete */ dlfb_free_urb_list(dev); if (info) { /* remove udlfb's sysfs interfaces */ /* remove udlfb's sysfs interfaces */ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_bin_file(info->dev, &edid_attr); device_remove_bin_file(info->dev, &edid_attr); /* it's safe to uncomment next line if your kernel doesn't yet have this function exported */ unlink_framebuffer(info); unlink_framebuffer(info); } usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL); dev->udev = NULL; dev->gdev = NULL; /* if clients still have us open, will be freed on last close */ /* if clients still have us open, will be freed on last close */ if (dev->fb_count == 0) if (dev->fb_count == 0) Loading Loading @@ -1806,12 +1829,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev) int ret; int ret; unsigned long flags; unsigned long flags; pr_notice("Waiting for completes and freeing all render urbs\n"); pr_notice("Freeing all render urbs\n"); /* keep waiting and freeing, until we've got 'em all */ /* keep waiting and freeing, until we've got 'em all */ while (count--) { while (count--) { /* Getting interrupted means a leak, but ok at shutdown*/ /* Getting interrupted means a leak, but ok at disconnect */ ret = down_interruptible(&dev->urbs.limit_sem); ret = down_interruptible(&dev->urbs.limit_sem); if (ret) if (ret) break; break; Loading @@ -1833,6 +1856,7 @@ static void dlfb_free_urb_list(struct dlfb_data *dev) kfree(node); kfree(node); } } dev->urbs.count = 0; } } static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) Loading Loading @@ -1948,6 +1972,9 @@ MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes"); module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)"); MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " "Jaya Kumar <jayakumar.lkml@gmail.com>, " "Jaya Kumar <jayakumar.lkml@gmail.com>, " "Bernie Thompson <bernie@plugable.com>"); "Bernie Thompson <bernie@plugable.com>"); Loading
include/video/udlfb.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ struct dlfb_data { char *backing_buffer; char *backing_buffer; int fb_count; int fb_count; bool virtualized; /* true when physical usb device not present */ bool virtualized; /* true when physical usb device not present */ struct delayed_work init_framebuffer_work; struct delayed_work free_framebuffer_work; struct delayed_work free_framebuffer_work; atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 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 lost_pixels; /* 1 = a render op failed. Need screen refresh */ Loading