fbdev fixes for kernel 6.1-rc3:

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.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCY16ulQAKCRD3ErUQojoP
 XyvDAP9ZhF0SjbnRBwHAU9ZYC7XpCwcoqBRWFCCU7mmmbkXrJAD9F1LcEwZPGyn/
 5/hiTwzM8ioJz6HB3r04M88bl4b1cwI=
 =SnCh
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2022-10-30 11:31:14 -07:00
commit b72018ab82
11 changed files with 48 additions and 39 deletions

View File

@ -91,7 +91,7 @@ struct SiS_Ext {
unsigned char VB_ExtTVYFilterIndex;
unsigned char VB_ExtTVYFilterIndexROM661;
unsigned char REFindex;
char ROMMODEIDX661;
signed char ROMMODEIDX661;
};
struct SiS_Ext2 {

View File

@ -1796,6 +1796,7 @@ failed_ioremap:
failed_regions:
cyberpro_free_fb_info(cfb);
failed_release:
pci_disable_device(dev);
return err;
}
@ -1812,6 +1813,7 @@ static void cyberpro_pci_remove(struct pci_dev *dev)
int_cfb_info = NULL;
pci_release_regions(dev);
pci_disable_device(dev);
}
}

View File

@ -1076,7 +1076,8 @@ static int fb_remove(struct platform_device *dev)
if (par->lcd_supply) {
ret = regulator_disable(par->lcd_supply);
if (ret)
return ret;
dev_warn(&dev->dev, "Failed to disable regulator (%pe)\n",
ERR_PTR(ret));
}
lcd_disable_raster(DA8XX_FRAME_WAIT);

View File

@ -1060,14 +1060,14 @@ static const struct fb_ops gbefb_ops = {
static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%u\n", gbe_mem_size);
return sysfs_emit(buf, "%u\n", gbe_mem_size);
}
static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
return sysfs_emit(buf, "%d\n", gbe_revision);
}
static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);

View File

@ -202,7 +202,7 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int
* and destination blitting areas overlap and
* adapt the bitmap addresses synchronously
* if the coordinates exceed the valid range.
* The the areas do not overlap, we do our
* The areas do not overlap, we do our
* normal check.
*/
if((mymax - mymin) < height) {

View File

@ -148,7 +148,7 @@ struct SiS_Ext {
unsigned char VB_ExtTVYFilterIndex;
unsigned char VB_ExtTVYFilterIndexROM661;
unsigned char REFindex;
char ROMMODEIDX661;
signed char ROMMODEIDX661;
};
struct SiS_Ext2 {

View File

@ -1166,7 +1166,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
ctrl &= SM501_DC_CRT_CONTROL_SEL;
return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
return sysfs_emit(buf, "%s\n", ctrl ? "crt" : "panel");
}
/* sm501fb_crtsrc_show

View File

@ -97,7 +97,6 @@ struct ufx_data {
struct kref kref;
int fb_count;
bool virtualized; /* true when physical usb device not present */
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 */
u8 *edid; /* null until we read edid from hw or get from sysfs */
@ -1117,15 +1116,24 @@ static void ufx_free(struct kref *kref)
{
struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
/* this function will wait for all in-flight urbs to complete */
if (dev->urbs.count > 0)
ufx_free_urb_list(dev);
pr_debug("freeing ufx_data %p", dev);
kfree(dev);
}
static void ufx_ops_destory(struct fb_info *info)
{
struct ufx_data *dev = info->par;
int node = info->node;
/* Assume info structure is freed after this point */
framebuffer_release(info);
pr_debug("fb_info for /dev/fb%d has been freed", node);
/* release reference taken by kref_init in probe() */
kref_put(&dev->kref, ufx_free);
}
static void ufx_release_urb_work(struct work_struct *work)
{
struct urb_node *unode = container_of(work, struct urb_node,
@ -1134,14 +1142,9 @@ static void ufx_release_urb_work(struct work_struct *work)
up(&unode->dev->urbs.limit_sem);
}
static void ufx_free_framebuffer_work(struct work_struct *work)
static void ufx_free_framebuffer(struct ufx_data *dev)
{
struct ufx_data *dev = container_of(work, struct ufx_data,
free_framebuffer_work.work);
struct fb_info *info = dev->info;
int node = info->node;
unregister_framebuffer(info);
if (info->cmap.len != 0)
fb_dealloc_cmap(&info->cmap);
@ -1153,11 +1156,6 @@ static void ufx_free_framebuffer_work(struct work_struct *work)
dev->info = NULL;
/* Assume info structure is freed after this point */
framebuffer_release(info);
pr_debug("fb_info for /dev/fb%d has been freed", node);
/* ref taken in probe() as part of registering framebfufer */
kref_put(&dev->kref, ufx_free);
}
@ -1169,11 +1167,13 @@ static int ufx_ops_release(struct fb_info *info, int user)
{
struct ufx_data *dev = info->par;
mutex_lock(&disconnect_mutex);
dev->fb_count--;
/* We can't free fb_info here - fbmem will touch it when we return */
if (dev->virtualized && (dev->fb_count == 0))
schedule_delayed_work(&dev->free_framebuffer_work, HZ);
ufx_free_framebuffer(dev);
if ((dev->fb_count == 0) && (info->fbdefio)) {
fb_deferred_io_cleanup(info);
@ -1186,6 +1186,8 @@ static int ufx_ops_release(struct fb_info *info, int user)
kref_put(&dev->kref, ufx_free);
mutex_unlock(&disconnect_mutex);
return 0;
}
@ -1292,6 +1294,7 @@ static const struct fb_ops ufx_ops = {
.fb_blank = ufx_ops_blank,
.fb_check_var = ufx_ops_check_var,
.fb_set_par = ufx_ops_set_par,
.fb_destroy = ufx_ops_destory,
};
/* Assumes &info->lock held by caller
@ -1673,9 +1676,6 @@ static int ufx_usb_probe(struct usb_interface *interface,
goto destroy_modedb;
}
INIT_DELAYED_WORK(&dev->free_framebuffer_work,
ufx_free_framebuffer_work);
retval = ufx_reg_read(dev, 0x3000, &id_rev);
check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
@ -1748,10 +1748,12 @@ e_nomem:
static void ufx_usb_disconnect(struct usb_interface *interface)
{
struct ufx_data *dev;
struct fb_info *info;
mutex_lock(&disconnect_mutex);
dev = usb_get_intfdata(interface);
info = dev->info;
pr_debug("USB disconnect starting\n");
@ -1765,12 +1767,15 @@ static void ufx_usb_disconnect(struct usb_interface *interface)
/* if clients still have us open, will be freed on last close */
if (dev->fb_count == 0)
schedule_delayed_work(&dev->free_framebuffer_work, 0);
ufx_free_framebuffer(dev);
/* release reference taken by kref_init in probe() */
kref_put(&dev->kref, ufx_free);
/* this function will wait for all in-flight urbs to complete */
if (dev->urbs.count > 0)
ufx_free_urb_list(dev);
/* consider ufx_data freed */
pr_debug("freeing ufx_data %p", dev);
unregister_framebuffer(info);
mutex_unlock(&disconnect_mutex);
}

View File

@ -1055,7 +1055,8 @@ stifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct stifb_info *fb = container_of(info, struct stifb_info, info);
if (rect->rop != ROP_COPY)
if (rect->rop != ROP_COPY ||
(fb->id == S9000_ID_HCRX && fb->info.var.bits_per_pixel == 32))
return cfb_fillrect(info, rect);
SETUP_HW(fb);

View File

@ -376,7 +376,7 @@ err_cmap:
return rc;
}
static int xilinxfb_release(struct device *dev)
static void xilinxfb_release(struct device *dev)
{
struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev);
@ -402,8 +402,6 @@ static int xilinxfb_release(struct device *dev)
if (!(drvdata->flags & BUS_ACCESS_FLAG))
dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
#endif
return 0;
}
/* ---------------------------------------------------------------------
@ -480,7 +478,9 @@ static int xilinxfb_of_probe(struct platform_device *pdev)
static int xilinxfb_of_remove(struct platform_device *op)
{
return xilinxfb_release(&op->dev);
xilinxfb_release(&op->dev);
return 0;
}
/* Match table for of_platform binding */

View File

@ -555,7 +555,7 @@ static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || \
defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || \
defined(__arm__) || defined(__aarch64__)
defined(__arm__) || defined(__aarch64__) || defined(__mips__)
#define fb_readb __raw_readb
#define fb_readw __raw_readw