Commit 83e79ae3 authored by Daniel Vetter's avatar Daniel Vetter

Merge tag 'drm-misc-fixes-2023-01-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

Several fixes to fix the error path of dma_buf_export, add a missing
structure declaration resulting in a compiler warning, fix the GEM
handle refcounting in panfrost, fix a corrupted image with AFBC on
meson, a memleak in virtio, improper plane width for imx, and a lockup
in drm_sched_entity_kill()
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20230105074909.qd2h23hpxac4lxi7@houat
parents c8de5262 69555549
...@@ -168,14 +168,11 @@ void dma_buf_uninit_sysfs_statistics(void) ...@@ -168,14 +168,11 @@ void dma_buf_uninit_sysfs_statistics(void)
kset_unregister(dma_buf_stats_kset); kset_unregister(dma_buf_stats_kset);
} }
int dma_buf_stats_setup(struct dma_buf *dmabuf) int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file)
{ {
struct dma_buf_sysfs_entry *sysfs_entry; struct dma_buf_sysfs_entry *sysfs_entry;
int ret; int ret;
if (!dmabuf || !dmabuf->file)
return -EINVAL;
if (!dmabuf->exp_name) { if (!dmabuf->exp_name) {
pr_err("exporter name must not be empty if stats needed\n"); pr_err("exporter name must not be empty if stats needed\n");
return -EINVAL; return -EINVAL;
...@@ -192,7 +189,7 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf) ...@@ -192,7 +189,7 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf)
/* create the directory for buffer stats */ /* create the directory for buffer stats */
ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL, ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL,
"%lu", file_inode(dmabuf->file)->i_ino); "%lu", file_inode(file)->i_ino);
if (ret) if (ret)
goto err_sysfs_dmabuf; goto err_sysfs_dmabuf;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
int dma_buf_init_sysfs_statistics(void); int dma_buf_init_sysfs_statistics(void);
void dma_buf_uninit_sysfs_statistics(void); void dma_buf_uninit_sysfs_statistics(void);
int dma_buf_stats_setup(struct dma_buf *dmabuf); int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file);
void dma_buf_stats_teardown(struct dma_buf *dmabuf); void dma_buf_stats_teardown(struct dma_buf *dmabuf);
#else #else
...@@ -25,7 +25,7 @@ static inline int dma_buf_init_sysfs_statistics(void) ...@@ -25,7 +25,7 @@ static inline int dma_buf_init_sysfs_statistics(void)
static inline void dma_buf_uninit_sysfs_statistics(void) {} static inline void dma_buf_uninit_sysfs_statistics(void) {}
static inline int dma_buf_stats_setup(struct dma_buf *dmabuf) static inline int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file)
{ {
return 0; return 0;
} }
......
...@@ -95,10 +95,11 @@ static int dma_buf_file_release(struct inode *inode, struct file *file) ...@@ -95,10 +95,11 @@ static int dma_buf_file_release(struct inode *inode, struct file *file)
return -EINVAL; return -EINVAL;
dmabuf = file->private_data; dmabuf = file->private_data;
if (dmabuf) {
mutex_lock(&db_list.lock); mutex_lock(&db_list.lock);
list_del(&dmabuf->list_node); list_del(&dmabuf->list_node);
mutex_unlock(&db_list.lock); mutex_unlock(&db_list.lock);
}
return 0; return 0;
} }
...@@ -528,17 +529,17 @@ static inline int is_dma_buf_file(struct file *file) ...@@ -528,17 +529,17 @@ static inline int is_dma_buf_file(struct file *file)
return file->f_op == &dma_buf_fops; return file->f_op == &dma_buf_fops;
} }
static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags) static struct file *dma_buf_getfile(size_t size, int flags)
{ {
static atomic64_t dmabuf_inode = ATOMIC64_INIT(0); static atomic64_t dmabuf_inode = ATOMIC64_INIT(0);
struct file *file;
struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb); struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb);
struct file *file;
if (IS_ERR(inode)) if (IS_ERR(inode))
return ERR_CAST(inode); return ERR_CAST(inode);
inode->i_size = dmabuf->size; inode->i_size = size;
inode_set_bytes(inode, dmabuf->size); inode_set_bytes(inode, size);
/* /*
* The ->i_ino acquired from get_next_ino() is not unique thus * The ->i_ino acquired from get_next_ino() is not unique thus
...@@ -552,8 +553,6 @@ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags) ...@@ -552,8 +553,6 @@ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
flags, &dma_buf_fops); flags, &dma_buf_fops);
if (IS_ERR(file)) if (IS_ERR(file))
goto err_alloc_file; goto err_alloc_file;
file->private_data = dmabuf;
file->f_path.dentry->d_fsdata = dmabuf;
return file; return file;
...@@ -619,19 +618,11 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) ...@@ -619,19 +618,11 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
size_t alloc_size = sizeof(struct dma_buf); size_t alloc_size = sizeof(struct dma_buf);
int ret; int ret;
if (!exp_info->resv) if (WARN_ON(!exp_info->priv || !exp_info->ops
alloc_size += sizeof(struct dma_resv); || !exp_info->ops->map_dma_buf
else || !exp_info->ops->unmap_dma_buf
/* prevent &dma_buf[1] == dma_buf->resv */ || !exp_info->ops->release))
alloc_size += 1;
if (WARN_ON(!exp_info->priv
|| !exp_info->ops
|| !exp_info->ops->map_dma_buf
|| !exp_info->ops->unmap_dma_buf
|| !exp_info->ops->release)) {
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
}
if (WARN_ON(exp_info->ops->cache_sgt_mapping && if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
(exp_info->ops->pin || exp_info->ops->unpin))) (exp_info->ops->pin || exp_info->ops->unpin)))
...@@ -643,10 +634,21 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) ...@@ -643,10 +634,21 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
if (!try_module_get(exp_info->owner)) if (!try_module_get(exp_info->owner))
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
file = dma_buf_getfile(exp_info->size, exp_info->flags);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
goto err_module;
}
if (!exp_info->resv)
alloc_size += sizeof(struct dma_resv);
else
/* prevent &dma_buf[1] == dma_buf->resv */
alloc_size += 1;
dmabuf = kzalloc(alloc_size, GFP_KERNEL); dmabuf = kzalloc(alloc_size, GFP_KERNEL);
if (!dmabuf) { if (!dmabuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_module; goto err_file;
} }
dmabuf->priv = exp_info->priv; dmabuf->priv = exp_info->priv;
...@@ -658,43 +660,35 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) ...@@ -658,43 +660,35 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
init_waitqueue_head(&dmabuf->poll); init_waitqueue_head(&dmabuf->poll);
dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll; dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
dmabuf->cb_in.active = dmabuf->cb_out.active = 0; dmabuf->cb_in.active = dmabuf->cb_out.active = 0;
INIT_LIST_HEAD(&dmabuf->attachments);
if (!resv) { if (!resv) {
resv = (struct dma_resv *)&dmabuf[1]; dmabuf->resv = (struct dma_resv *)&dmabuf[1];
dma_resv_init(resv); dma_resv_init(dmabuf->resv);
} else {
dmabuf->resv = resv;
} }
dmabuf->resv = resv;
file = dma_buf_getfile(dmabuf, exp_info->flags); ret = dma_buf_stats_setup(dmabuf, file);
if (IS_ERR(file)) { if (ret)
ret = PTR_ERR(file);
goto err_dmabuf; goto err_dmabuf;
}
file->private_data = dmabuf;
file->f_path.dentry->d_fsdata = dmabuf;
dmabuf->file = file; dmabuf->file = file;
INIT_LIST_HEAD(&dmabuf->attachments);
mutex_lock(&db_list.lock); mutex_lock(&db_list.lock);
list_add(&dmabuf->list_node, &db_list.head); list_add(&dmabuf->list_node, &db_list.head);
mutex_unlock(&db_list.lock); mutex_unlock(&db_list.lock);
ret = dma_buf_stats_setup(dmabuf);
if (ret)
goto err_sysfs;
return dmabuf; return dmabuf;
err_sysfs:
/*
* Set file->f_path.dentry->d_fsdata to NULL so that when
* dma_buf_release() gets invoked by dentry_ops, it exits
* early before calling the release() dma_buf op.
*/
file->f_path.dentry->d_fsdata = NULL;
fput(file);
err_dmabuf: err_dmabuf:
if (!resv)
dma_resv_fini(dmabuf->resv);
kfree(dmabuf); kfree(dmabuf);
err_file:
fput(file);
err_module: err_module:
module_put(exp_info->owner); module_put(exp_info->owner);
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -614,6 +614,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -614,6 +614,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
break; break;
} }
if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_BG)
width = ipu_src_rect_width(new_state);
else
width = drm_rect_width(&new_state->src) >> 16;
eba = drm_plane_state_to_eba(new_state, 0); eba = drm_plane_state_to_eba(new_state, 0);
/* /*
...@@ -622,8 +627,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -622,8 +627,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
*/ */
if (ipu_state->use_pre) { if (ipu_state->use_pre) {
axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, width,
ipu_src_rect_width(new_state),
drm_rect_height(&new_state->src) >> 16, drm_rect_height(&new_state->src) >> 16,
fb->pitches[0], fb->format->format, fb->pitches[0], fb->format->format,
fb->modifier, &eba); fb->modifier, &eba);
...@@ -678,9 +682,8 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -678,9 +682,8 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
break; break;
} }
ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8)); ipu_dmfc_config_wait4eot(ipu_plane->dmfc, width);
width = ipu_src_rect_width(new_state);
height = drm_rect_height(&new_state->src) >> 16; height = drm_rect_height(&new_state->src) >> 16;
info = drm_format_info(fb->format->format); info = drm_format_info(fb->format->format);
ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
...@@ -744,8 +747,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -744,8 +747,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16);
ipu_cpmem_zero(ipu_plane->alpha_ch); ipu_cpmem_zero(ipu_plane->alpha_ch);
ipu_cpmem_set_resolution(ipu_plane->alpha_ch, ipu_cpmem_set_resolution(ipu_plane->alpha_ch, width,
ipu_src_rect_width(new_state),
drm_rect_height(&new_state->src) >> 16); drm_rect_height(&new_state->src) >> 16);
ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
......
...@@ -436,15 +436,14 @@ void meson_viu_init(struct meson_drm *priv) ...@@ -436,15 +436,14 @@ void meson_viu_init(struct meson_drm *priv)
/* Initialize OSD1 fifo control register */ /* Initialize OSD1 fifo control register */
reg = VIU_OSD_DDR_PRIORITY_URGENT | reg = VIU_OSD_DDR_PRIORITY_URGENT |
VIU_OSD_HOLD_FIFO_LINES(31) |
VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
reg |= VIU_OSD_BURST_LENGTH_32; reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31));
else else
reg |= VIU_OSD_BURST_LENGTH_64; reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4));
writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
......
...@@ -82,6 +82,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, ...@@ -82,6 +82,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data,
struct panfrost_gem_object *bo; struct panfrost_gem_object *bo;
struct drm_panfrost_create_bo *args = data; struct drm_panfrost_create_bo *args = data;
struct panfrost_gem_mapping *mapping; struct panfrost_gem_mapping *mapping;
int ret;
if (!args->size || args->pad || if (!args->size || args->pad ||
(args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP))) (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP)))
...@@ -92,21 +93,29 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, ...@@ -92,21 +93,29 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data,
!(args->flags & PANFROST_BO_NOEXEC)) !(args->flags & PANFROST_BO_NOEXEC))
return -EINVAL; return -EINVAL;
bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, bo = panfrost_gem_create(dev, args->size, args->flags);
&args->handle);
if (IS_ERR(bo)) if (IS_ERR(bo))
return PTR_ERR(bo); return PTR_ERR(bo);
ret = drm_gem_handle_create(file, &bo->base.base, &args->handle);
if (ret)
goto out;
mapping = panfrost_gem_mapping_get(bo, priv); mapping = panfrost_gem_mapping_get(bo, priv);
if (!mapping) { if (mapping) {
drm_gem_object_put(&bo->base.base); args->offset = mapping->mmnode.start << PAGE_SHIFT;
return -EINVAL; panfrost_gem_mapping_put(mapping);
} else {
/* This can only happen if the handle from
* drm_gem_handle_create() has already been guessed and freed
* by user space
*/
ret = -EINVAL;
} }
args->offset = mapping->mmnode.start << PAGE_SHIFT; out:
panfrost_gem_mapping_put(mapping); drm_gem_object_put(&bo->base.base);
return ret;
return 0;
} }
/** /**
......
...@@ -235,12 +235,8 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t ...@@ -235,12 +235,8 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t
} }
struct panfrost_gem_object * struct panfrost_gem_object *
panfrost_gem_create_with_handle(struct drm_file *file_priv, panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags)
struct drm_device *dev, size_t size,
u32 flags,
uint32_t *handle)
{ {
int ret;
struct drm_gem_shmem_object *shmem; struct drm_gem_shmem_object *shmem;
struct panfrost_gem_object *bo; struct panfrost_gem_object *bo;
...@@ -256,16 +252,6 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv, ...@@ -256,16 +252,6 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv,
bo->noexec = !!(flags & PANFROST_BO_NOEXEC); bo->noexec = !!(flags & PANFROST_BO_NOEXEC);
bo->is_heap = !!(flags & PANFROST_BO_HEAP); bo->is_heap = !!(flags & PANFROST_BO_HEAP);
/*
* Allocate an id of idr table where the obj is registered
* and handle has the id what user can see.
*/
ret = drm_gem_handle_create(file_priv, &shmem->base, handle);
/* drop reference from allocate - handle holds it now. */
drm_gem_object_put(&shmem->base);
if (ret)
return ERR_PTR(ret);
return bo; return bo;
} }
......
...@@ -69,10 +69,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -69,10 +69,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev,
struct sg_table *sgt); struct sg_table *sgt);
struct panfrost_gem_object * struct panfrost_gem_object *
panfrost_gem_create_with_handle(struct drm_file *file_priv, panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags);
struct drm_device *dev, size_t size,
u32 flags,
uint32_t *handle);
int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv); int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv);
void panfrost_gem_close(struct drm_gem_object *obj, void panfrost_gem_close(struct drm_gem_object *obj,
......
...@@ -184,7 +184,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, ...@@ -184,7 +184,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object_array *objs = NULL; struct virtio_gpu_object_array *objs = NULL;
struct drm_gem_shmem_object *shmem_obj; struct drm_gem_shmem_object *shmem_obj;
struct virtio_gpu_object *bo; struct virtio_gpu_object *bo;
struct virtio_gpu_mem_entry *ents; struct virtio_gpu_mem_entry *ents = NULL;
unsigned int nents; unsigned int nents;
int ret; int ret;
...@@ -210,7 +210,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, ...@@ -210,7 +210,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
ret = -ENOMEM; ret = -ENOMEM;
objs = virtio_gpu_array_alloc(1); objs = virtio_gpu_array_alloc(1);
if (!objs) if (!objs)
goto err_put_id; goto err_free_entry;
virtio_gpu_array_add_obj(objs, &bo->base.base); virtio_gpu_array_add_obj(objs, &bo->base.base);
ret = virtio_gpu_array_lock_resv(objs); ret = virtio_gpu_array_lock_resv(objs);
...@@ -239,6 +239,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, ...@@ -239,6 +239,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
err_put_objs: err_put_objs:
virtio_gpu_array_put_free(objs); virtio_gpu_array_put_free(objs);
err_free_entry:
kvfree(ents);
err_put_id: err_put_id:
virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle); virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
err_free_gem: err_free_gem:
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/types.h> #include <linux/types.h>
struct drm_atomic_state;
struct drm_crtc; struct drm_crtc;
struct drm_framebuffer; struct drm_framebuffer;
struct drm_modeset_acquire_ctx; struct drm_modeset_acquire_ctx;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment