forked from Minki/linux
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:
commit
b72018ab82
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user