+31
-26
drivers/video/fbdev/smscufx.c
+31
-26
drivers/video/fbdev/smscufx.c
···
97
97
struct kref kref;
98
98
int fb_count;
99
99
bool virtualized; /* true when physical usb device not present */
100
-
struct delayed_work free_framebuffer_work;
101
100
atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
102
101
atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
103
102
u8 *edid; /* null until we read edid from hw or get from sysfs */
···
1116
1117
{
1117
1118
struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
1118
1119
1119
-
/* this function will wait for all in-flight urbs to complete */
1120
-
if (dev->urbs.count > 0)
1121
-
ufx_free_urb_list(dev);
1122
-
1123
-
pr_debug("freeing ufx_data %p", dev);
1124
-
1125
1120
kfree(dev);
1126
1121
}
1122
+
1123
+
static void ufx_ops_destory(struct fb_info *info)
1124
+
{
1125
+
struct ufx_data *dev = info->par;
1126
+
int node = info->node;
1127
+
1128
+
/* Assume info structure is freed after this point */
1129
+
framebuffer_release(info);
1130
+
1131
+
pr_debug("fb_info for /dev/fb%d has been freed", node);
1132
+
1133
+
/* release reference taken by kref_init in probe() */
1134
+
kref_put(&dev->kref, ufx_free);
1135
+
}
1136
+
1127
1137
1128
1138
static void ufx_release_urb_work(struct work_struct *work)
1129
1139
{
···
1142
1134
up(&unode->dev->urbs.limit_sem);
1143
1135
}
1144
1136
1145
-
static void ufx_free_framebuffer_work(struct work_struct *work)
1137
+
static void ufx_free_framebuffer(struct ufx_data *dev)
1146
1138
{
1147
-
struct ufx_data *dev = container_of(work, struct ufx_data,
1148
-
free_framebuffer_work.work);
1149
1139
struct fb_info *info = dev->info;
1150
-
int node = info->node;
1151
-
1152
-
unregister_framebuffer(info);
1153
1140
1154
1141
if (info->cmap.len != 0)
1155
1142
fb_dealloc_cmap(&info->cmap);
···
1155
1152
fb_destroy_modelist(&info->modelist);
1156
1153
1157
1154
dev->info = NULL;
1158
-
1159
-
/* Assume info structure is freed after this point */
1160
-
framebuffer_release(info);
1161
-
1162
-
pr_debug("fb_info for /dev/fb%d has been freed", node);
1163
1155
1164
1156
/* ref taken in probe() as part of registering framebfufer */
1165
1157
kref_put(&dev->kref, ufx_free);
···
1167
1169
{
1168
1170
struct ufx_data *dev = info->par;
1169
1171
1172
+
mutex_lock(&disconnect_mutex);
1173
+
1170
1174
dev->fb_count--;
1171
1175
1172
1176
/* We can't free fb_info here - fbmem will touch it when we return */
1173
1177
if (dev->virtualized && (dev->fb_count == 0))
1174
-
schedule_delayed_work(&dev->free_framebuffer_work, HZ);
1178
+
ufx_free_framebuffer(dev);
1175
1179
1176
1180
if ((dev->fb_count == 0) && (info->fbdefio)) {
1177
1181
fb_deferred_io_cleanup(info);
···
1185
1185
info->node, user, dev->fb_count);
1186
1186
1187
1187
kref_put(&dev->kref, ufx_free);
1188
+
1189
+
mutex_unlock(&disconnect_mutex);
1188
1190
1189
1191
return 0;
1190
1192
}
···
1294
1292
.fb_blank = ufx_ops_blank,
1295
1293
.fb_check_var = ufx_ops_check_var,
1296
1294
.fb_set_par = ufx_ops_set_par,
1295
+
.fb_destroy = ufx_ops_destory,
1297
1296
};
1298
1297
1299
1298
/* Assumes &info->lock held by caller
···
1676
1673
goto destroy_modedb;
1677
1674
}
1678
1675
1679
-
INIT_DELAYED_WORK(&dev->free_framebuffer_work,
1680
-
ufx_free_framebuffer_work);
1681
-
1682
1676
retval = ufx_reg_read(dev, 0x3000, &id_rev);
1683
1677
check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
1684
1678
dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
···
1748
1748
static void ufx_usb_disconnect(struct usb_interface *interface)
1749
1749
{
1750
1750
struct ufx_data *dev;
1751
+
struct fb_info *info;
1751
1752
1752
1753
mutex_lock(&disconnect_mutex);
1753
1754
1754
1755
dev = usb_get_intfdata(interface);
1756
+
info = dev->info;
1755
1757
1756
1758
pr_debug("USB disconnect starting\n");
1757
1759
···
1767
1765
1768
1766
/* if clients still have us open, will be freed on last close */
1769
1767
if (dev->fb_count == 0)
1770
-
schedule_delayed_work(&dev->free_framebuffer_work, 0);
1768
+
ufx_free_framebuffer(dev);
1771
1769
1772
-
/* release reference taken by kref_init in probe() */
1773
-
kref_put(&dev->kref, ufx_free);
1770
+
/* this function will wait for all in-flight urbs to complete */
1771
+
if (dev->urbs.count > 0)
1772
+
ufx_free_urb_list(dev);
1774
1773
1775
-
/* consider ufx_data freed */
1774
+
pr_debug("freeing ufx_data %p", dev);
1775
+
1776
+
unregister_framebuffer(info);
1776
1777
1777
1778
mutex_unlock(&disconnect_mutex);
1778
1779
}