Merge tag 'fbdev-for-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev

Pull fbdev fixes from Helge Deller:
"A use-after-free bugfix in the smscufx driver and various minor error
path fixes, smaller build fixes, sysfs fixes and typos in comments in
the stifb, sisfb, da8xxfb, xilinxfb, sm501fb, gbefb and cyber2000fb
drivers"

* tag 'fbdev-for-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev:
fbdev: cyber2000fb: fix missing pci_disable_device()
fbdev: sisfb: use explicitly signed char
fbdev: smscufx: Fix several use-after-free bugs
fbdev: xilinxfb: Make xilinxfb_release() return void
fbdev: sisfb: fix repeated word in comment
fbdev: gbefb: Convert sysfs snprintf to sysfs_emit
fbdev: sm501fb: Convert sysfs snprintf to sysfs_emit
fbdev: stifb: Fall back to cfb_fillrect() on 32-bit HCRX cards
fbdev: da8xx-fb: Fix error handling in .remove()
fbdev: MIPS supports iomem addresses

Changed files
+48 -39
drivers
include
linux
+1 -1
drivers/usb/misc/sisusbvga/sisusb_struct.h
··· 91 91 unsigned char VB_ExtTVYFilterIndex; 92 92 unsigned char VB_ExtTVYFilterIndexROM661; 93 93 unsigned char REFindex; 94 - char ROMMODEIDX661; 94 + signed char ROMMODEIDX661; 95 95 }; 96 96 97 97 struct SiS_Ext2 {
+2
drivers/video/fbdev/cyber2000fb.c
··· 1796 1796 failed_regions: 1797 1797 cyberpro_free_fb_info(cfb); 1798 1798 failed_release: 1799 + pci_disable_device(dev); 1799 1800 return err; 1800 1801 } 1801 1802 ··· 1813 1812 int_cfb_info = NULL; 1814 1813 1815 1814 pci_release_regions(dev); 1815 + pci_disable_device(dev); 1816 1816 } 1817 1817 } 1818 1818
+2 -1
drivers/video/fbdev/da8xx-fb.c
··· 1076 1076 if (par->lcd_supply) { 1077 1077 ret = regulator_disable(par->lcd_supply); 1078 1078 if (ret) 1079 - return ret; 1079 + dev_warn(&dev->dev, "Failed to disable regulator (%pe)\n", 1080 + ERR_PTR(ret)); 1080 1081 } 1081 1082 1082 1083 lcd_disable_raster(DA8XX_FRAME_WAIT);
+2 -2
drivers/video/fbdev/gbefb.c
··· 1060 1060 1061 1061 static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf) 1062 1062 { 1063 - return snprintf(buf, PAGE_SIZE, "%u\n", gbe_mem_size); 1063 + return sysfs_emit(buf, "%u\n", gbe_mem_size); 1064 1064 } 1065 1065 1066 1066 static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL); 1067 1067 1068 1068 static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf) 1069 1069 { 1070 - return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision); 1070 + return sysfs_emit(buf, "%d\n", gbe_revision); 1071 1071 } 1072 1072 1073 1073 static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
+1 -1
drivers/video/fbdev/sis/sis_accel.c
··· 202 202 * and destination blitting areas overlap and 203 203 * adapt the bitmap addresses synchronously 204 204 * if the coordinates exceed the valid range. 205 - * The the areas do not overlap, we do our 205 + * The areas do not overlap, we do our 206 206 * normal check. 207 207 */ 208 208 if((mymax - mymin) < height) {
+1 -1
drivers/video/fbdev/sis/vstruct.h
··· 148 148 unsigned char VB_ExtTVYFilterIndex; 149 149 unsigned char VB_ExtTVYFilterIndexROM661; 150 150 unsigned char REFindex; 151 - char ROMMODEIDX661; 151 + signed char ROMMODEIDX661; 152 152 }; 153 153 154 154 struct SiS_Ext2 {
+1 -1
drivers/video/fbdev/sm501fb.c
··· 1166 1166 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 1167 1167 ctrl &= SM501_DC_CRT_CONTROL_SEL; 1168 1168 1169 - return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); 1169 + return sysfs_emit(buf, "%s\n", ctrl ? "crt" : "panel"); 1170 1170 } 1171 1171 1172 1172 /* sm501fb_crtsrc_show
+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 }
+2 -1
drivers/video/fbdev/stifb.c
··· 1055 1055 { 1056 1056 struct stifb_info *fb = container_of(info, struct stifb_info, info); 1057 1057 1058 - if (rect->rop != ROP_COPY) 1058 + if (rect->rop != ROP_COPY || 1059 + (fb->id == S9000_ID_HCRX && fb->info.var.bits_per_pixel == 32)) 1059 1060 return cfb_fillrect(info, rect); 1060 1061 1061 1062 SETUP_HW(fb);
+4 -4
drivers/video/fbdev/xilinxfb.c
··· 376 376 return rc; 377 377 } 378 378 379 - static int xilinxfb_release(struct device *dev) 379 + static void xilinxfb_release(struct device *dev) 380 380 { 381 381 struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev); 382 382 ··· 402 402 if (!(drvdata->flags & BUS_ACCESS_FLAG)) 403 403 dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); 404 404 #endif 405 - 406 - return 0; 407 405 } 408 406 409 407 /* --------------------------------------------------------------------- ··· 478 480 479 481 static int xilinxfb_of_remove(struct platform_device *op) 480 482 { 481 - return xilinxfb_release(&op->dev); 483 + xilinxfb_release(&op->dev); 484 + 485 + return 0; 482 486 } 483 487 484 488 /* Match table for of_platform binding */
+1 -1
include/linux/fb.h
··· 555 555 556 556 #elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || \ 557 557 defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || \ 558 - defined(__arm__) || defined(__aarch64__) 558 + defined(__arm__) || defined(__aarch64__) || defined(__mips__) 559 559 560 560 #define fb_readb __raw_readb 561 561 #define fb_readw __raw_readw