hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/video/fbdev/smscufx.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
34 *
....@@ -5,10 +6,6 @@
56 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
67 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
78 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
8
- *
9
- * This file is subject to the terms and conditions of the GNU General Public
10
- * License v2. See the file COPYING in the main directory of this archive for
11
- * more details.
129 *
1310 * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen,
1411 * and others.
....@@ -100,7 +97,6 @@
10097 struct kref kref;
10198 int fb_count;
10299 bool virtualized; /* true when physical usb device not present */
103
- struct delayed_work free_framebuffer_work;
104100 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
105101 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
106102 u8 *edid; /* null until we read edid from hw or get from sysfs */
....@@ -139,6 +135,8 @@
139135 static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
140136 static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
141137 static void ufx_free_urb_list(struct ufx_data *dev);
138
+
139
+static DEFINE_MUTEX(disconnect_mutex);
142140
143141 /* reads a control register */
144142 static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
....@@ -1073,9 +1071,13 @@
10731071 if (user == 0 && !console)
10741072 return -EBUSY;
10751073
1074
+ mutex_lock(&disconnect_mutex);
1075
+
10761076 /* If the USB device is gone, we don't accept new opens */
1077
- if (dev->virtualized)
1077
+ if (dev->virtualized) {
1078
+ mutex_unlock(&disconnect_mutex);
10781079 return -ENODEV;
1080
+ }
10791081
10801082 dev->fb_count++;
10811083
....@@ -1099,6 +1101,8 @@
10991101 pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
11001102 info->node, user, info, dev->fb_count);
11011103
1104
+ mutex_unlock(&disconnect_mutex);
1105
+
11021106 return 0;
11031107 }
11041108
....@@ -1111,14 +1115,23 @@
11111115 {
11121116 struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
11131117
1114
- /* this function will wait for all in-flight urbs to complete */
1115
- if (dev->urbs.count > 0)
1116
- ufx_free_urb_list(dev);
1117
-
1118
- pr_debug("freeing ufx_data %p", dev);
1119
-
11201118 kfree(dev);
11211119 }
1120
+
1121
+static void ufx_ops_destory(struct fb_info *info)
1122
+{
1123
+ struct ufx_data *dev = info->par;
1124
+ int node = info->node;
1125
+
1126
+ /* Assume info structure is freed after this point */
1127
+ framebuffer_release(info);
1128
+
1129
+ pr_debug("fb_info for /dev/fb%d has been freed", node);
1130
+
1131
+ /* release reference taken by kref_init in probe() */
1132
+ kref_put(&dev->kref, ufx_free);
1133
+}
1134
+
11221135
11231136 static void ufx_release_urb_work(struct work_struct *work)
11241137 {
....@@ -1128,14 +1141,9 @@
11281141 up(&unode->dev->urbs.limit_sem);
11291142 }
11301143
1131
-static void ufx_free_framebuffer_work(struct work_struct *work)
1144
+static void ufx_free_framebuffer(struct ufx_data *dev)
11321145 {
1133
- struct ufx_data *dev = container_of(work, struct ufx_data,
1134
- free_framebuffer_work.work);
11351146 struct fb_info *info = dev->info;
1136
- int node = info->node;
1137
-
1138
- unregister_framebuffer(info);
11391147
11401148 if (info->cmap.len != 0)
11411149 fb_dealloc_cmap(&info->cmap);
....@@ -1146,11 +1154,6 @@
11461154 fb_destroy_modelist(&info->modelist);
11471155
11481156 dev->info = NULL;
1149
-
1150
- /* Assume info structure is freed after this point */
1151
- framebuffer_release(info);
1152
-
1153
- pr_debug("fb_info for /dev/fb%d has been freed", node);
11541157
11551158 /* ref taken in probe() as part of registering framebfufer */
11561159 kref_put(&dev->kref, ufx_free);
....@@ -1163,23 +1166,26 @@
11631166 {
11641167 struct ufx_data *dev = info->par;
11651168
1169
+ mutex_lock(&disconnect_mutex);
1170
+
11661171 dev->fb_count--;
11671172
11681173 /* We can't free fb_info here - fbmem will touch it when we return */
11691174 if (dev->virtualized && (dev->fb_count == 0))
1170
- schedule_delayed_work(&dev->free_framebuffer_work, HZ);
1175
+ ufx_free_framebuffer(dev);
11711176
11721177 if ((dev->fb_count == 0) && (info->fbdefio)) {
11731178 fb_deferred_io_cleanup(info);
11741179 kfree(info->fbdefio);
11751180 info->fbdefio = NULL;
1176
- info->fbops->fb_mmap = ufx_ops_mmap;
11771181 }
11781182
11791183 pr_debug("released /dev/fb%d user=%d count=%d",
11801184 info->node, user, dev->fb_count);
11811185
11821186 kref_put(&dev->kref, ufx_free);
1187
+
1188
+ mutex_unlock(&disconnect_mutex);
11831189
11841190 return 0;
11851191 }
....@@ -1272,7 +1278,7 @@
12721278 return 0;
12731279 }
12741280
1275
-static struct fb_ops ufx_ops = {
1281
+static const struct fb_ops ufx_ops = {
12761282 .owner = THIS_MODULE,
12771283 .fb_read = fb_sys_read,
12781284 .fb_write = ufx_ops_write,
....@@ -1287,6 +1293,7 @@
12871293 .fb_blank = ufx_ops_blank,
12881294 .fb_check_var = ufx_ops_check_var,
12891295 .fb_set_par = ufx_ops_set_par,
1296
+ .fb_destroy = ufx_ops_destory,
12901297 };
12911298
12921299 /* Assumes &info->lock held by caller
....@@ -1653,26 +1660,20 @@
16531660
16541661 /* allocates framebuffer driver structure, not framebuffer memory */
16551662 info = framebuffer_alloc(0, &usbdev->dev);
1656
- if (!info) {
1657
- dev_err(dev->gdev, "framebuffer_alloc failed\n");
1663
+ if (!info)
16581664 goto e_nomem;
1659
- }
16601665
16611666 dev->info = info;
16621667 info->par = dev;
16631668 info->pseudo_palette = dev->pseudo_palette;
16641669 info->fbops = &ufx_ops;
1670
+ INIT_LIST_HEAD(&info->modelist);
16651671
16661672 retval = fb_alloc_cmap(&info->cmap, 256, 0);
16671673 if (retval < 0) {
16681674 dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
16691675 goto destroy_modedb;
16701676 }
1671
-
1672
- INIT_DELAYED_WORK(&dev->free_framebuffer_work,
1673
- ufx_free_framebuffer_work);
1674
-
1675
- INIT_LIST_HEAD(&info->modelist);
16761677
16771678 retval = ufx_reg_read(dev, 0x3000, &id_rev);
16781679 check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
....@@ -1746,8 +1747,12 @@
17461747 static void ufx_usb_disconnect(struct usb_interface *interface)
17471748 {
17481749 struct ufx_data *dev;
1750
+ struct fb_info *info;
1751
+
1752
+ mutex_lock(&disconnect_mutex);
17491753
17501754 dev = usb_get_intfdata(interface);
1755
+ info = dev->info;
17511756
17521757 pr_debug("USB disconnect starting\n");
17531758
....@@ -1761,12 +1766,17 @@
17611766
17621767 /* if clients still have us open, will be freed on last close */
17631768 if (dev->fb_count == 0)
1764
- schedule_delayed_work(&dev->free_framebuffer_work, 0);
1769
+ ufx_free_framebuffer(dev);
17651770
1766
- /* release reference taken by kref_init in probe() */
1767
- kref_put(&dev->kref, ufx_free);
1771
+ /* this function will wait for all in-flight urbs to complete */
1772
+ if (dev->urbs.count > 0)
1773
+ ufx_free_urb_list(dev);
17681774
1769
- /* consider ufx_data freed */
1775
+ pr_debug("freeing ufx_data %p", dev);
1776
+
1777
+ unregister_framebuffer(info);
1778
+
1779
+ mutex_unlock(&disconnect_mutex);
17701780 }
17711781
17721782 static struct usb_driver ufx_driver = {