Commit 2879b482 authored by Daniel Vetter's avatar Daniel Vetter

Merge tag 'drm-misc-fixes-2024-07-04' of...

Merge tag 'drm-misc-fixes-2024-07-04' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes

drm-misc-fixes for v6.10-rc7:
- Add panel quirks.
- Firmware sysfb refcount fix.
- Another null pointer mode deref fix for nouveau.
- Panthor sync and uobj fixes.
- Fix fbdev regression since v6.7.
- Delay free imported bo in ttm to fix lockdep splat.
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ffba0c63-2798-40b6-948d-361cd3b14e9f@linux.intel.com
parents cfbce3bc d99fbd9a
...@@ -101,8 +101,10 @@ static __init struct device *sysfb_parent_dev(const struct screen_info *si) ...@@ -101,8 +101,10 @@ static __init struct device *sysfb_parent_dev(const struct screen_info *si)
if (IS_ERR(pdev)) { if (IS_ERR(pdev)) {
return ERR_CAST(pdev); return ERR_CAST(pdev);
} else if (pdev) { } else if (pdev) {
if (!sysfb_pci_dev_is_enabled(pdev)) if (!sysfb_pci_dev_is_enabled(pdev)) {
pci_dev_put(pdev);
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
}
return &pdev->dev; return &pdev->dev;
} }
...@@ -137,7 +139,7 @@ static __init int sysfb_init(void) ...@@ -137,7 +139,7 @@ static __init int sysfb_init(void)
if (compatible) { if (compatible) {
pd = sysfb_create_simplefb(si, &mode, parent); pd = sysfb_create_simplefb(si, &mode, parent);
if (!IS_ERR(pd)) if (!IS_ERR(pd))
goto unlock_mutex; goto put_device;
} }
/* if the FB is incompatible, create a legacy framebuffer device */ /* if the FB is incompatible, create a legacy framebuffer device */
...@@ -155,7 +157,7 @@ static __init int sysfb_init(void) ...@@ -155,7 +157,7 @@ static __init int sysfb_init(void)
pd = platform_device_alloc(name, 0); pd = platform_device_alloc(name, 0);
if (!pd) { if (!pd) {
ret = -ENOMEM; ret = -ENOMEM;
goto unlock_mutex; goto put_device;
} }
pd->dev.parent = parent; pd->dev.parent = parent;
...@@ -170,9 +172,11 @@ static __init int sysfb_init(void) ...@@ -170,9 +172,11 @@ static __init int sysfb_init(void)
if (ret) if (ret)
goto err; goto err;
goto unlock_mutex; goto put_device;
err: err:
platform_device_put(pd); platform_device_put(pd);
put_device:
put_device(parent);
unlock_mutex: unlock_mutex:
mutex_unlock(&disable_lock); mutex_unlock(&disable_lock);
return ret; return ret;
......
...@@ -84,7 +84,8 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -84,7 +84,8 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
sizes->surface_width, sizes->surface_height, sizes->surface_width, sizes->surface_height,
sizes->surface_bpp); sizes->surface_bpp);
format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp,
sizes->surface_depth);
buffer = drm_client_framebuffer_create(client, sizes->surface_width, buffer = drm_client_framebuffer_create(client, sizes->surface_width,
sizes->surface_height, format); sizes->surface_height, format);
if (IS_ERR(buffer)) if (IS_ERR(buffer))
......
...@@ -420,13 +420,20 @@ static const struct dmi_system_id orientation_data[] = { ...@@ -420,13 +420,20 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
}, },
.driver_data = (void *)&lcd1280x1920_rightside_up, .driver_data = (void *)&lcd1280x1920_rightside_up,
}, { /* Valve Steam Deck */ }, { /* Valve Steam Deck (Jupiter) */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"), DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
}, },
.driver_data = (void *)&lcd800x1280_rightside_up, .driver_data = (void *)&lcd800x1280_rightside_up,
}, { /* Valve Steam Deck (Galileo) */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
}, { /* VIOS LTH17 */ }, { /* VIOS LTH17 */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
......
...@@ -1001,6 +1001,9 @@ nouveau_connector_get_modes(struct drm_connector *connector) ...@@ -1001,6 +1001,9 @@ nouveau_connector_get_modes(struct drm_connector *connector)
struct drm_display_mode *mode; struct drm_display_mode *mode;
mode = drm_mode_duplicate(dev, nv_connector->native_mode); mode = drm_mode_duplicate(dev, nv_connector->native_mode);
if (!mode)
return 0;
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
ret = 1; ret = 1;
} }
......
...@@ -86,15 +86,15 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, ...@@ -86,15 +86,15 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride,
int ret = 0; int ret = 0;
void *out_alloc; void *out_alloc;
if (!in->count)
return NULL;
/* User stride must be at least the minimum object size, otherwise it might /* User stride must be at least the minimum object size, otherwise it might
* lack useful information. * lack useful information.
*/ */
if (in->stride < min_stride) if (in->stride < min_stride)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (!in->count)
return NULL;
out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL); out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL);
if (!out_alloc) if (!out_alloc)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
...@@ -458,6 +458,16 @@ struct panthor_queue { ...@@ -458,6 +458,16 @@ struct panthor_queue {
/** @seqno: Sequence number of the last initialized fence. */ /** @seqno: Sequence number of the last initialized fence. */
atomic64_t seqno; atomic64_t seqno;
/**
* @last_fence: Fence of the last submitted job.
*
* We return this fence when we get an empty command stream.
* This way, we are guaranteed that all earlier jobs have completed
* when drm_sched_job::s_fence::finished without having to feed
* the CS ring buffer with a dummy job that only signals the fence.
*/
struct dma_fence *last_fence;
/** /**
* @in_flight_jobs: List containing all in-flight jobs. * @in_flight_jobs: List containing all in-flight jobs.
* *
...@@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue * ...@@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue *
panthor_kernel_bo_destroy(queue->ringbuf); panthor_kernel_bo_destroy(queue->ringbuf);
panthor_kernel_bo_destroy(queue->iface.mem); panthor_kernel_bo_destroy(queue->iface.mem);
/* Release the last_fence we were holding, if any. */
dma_fence_put(queue->fence_ctx.last_fence);
kfree(queue); kfree(queue);
} }
...@@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work) ...@@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work)
spin_lock(&queue->fence_ctx.lock); spin_lock(&queue->fence_ctx.lock);
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) { list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
if (!job->call_info.size)
continue;
if (syncobj->seqno < job->done_fence->seqno) if (syncobj->seqno < job->done_fence->seqno)
break; break;
...@@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job) ...@@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job)
static_assert(sizeof(call_instrs) % 64 == 0, static_assert(sizeof(call_instrs) % 64 == 0,
"call_instrs is not aligned on a cacheline"); "call_instrs is not aligned on a cacheline");
/* Stream size is zero, nothing to do => return a NULL fence and let /* Stream size is zero, nothing to do except making sure all previously
* drm_sched signal the parent. * submitted jobs are done before we signal the
* drm_sched_job::s_fence::finished fence.
*/ */
if (!job->call_info.size) if (!job->call_info.size) {
return NULL; job->done_fence = dma_fence_get(queue->fence_ctx.last_fence);
return dma_fence_get(job->done_fence);
}
ret = pm_runtime_resume_and_get(ptdev->base.dev); ret = pm_runtime_resume_and_get(ptdev->base.dev);
if (drm_WARN_ON(&ptdev->base, ret)) if (drm_WARN_ON(&ptdev->base, ret))
...@@ -2928,6 +2941,10 @@ queue_run_job(struct drm_sched_job *sched_job) ...@@ -2928,6 +2941,10 @@ queue_run_job(struct drm_sched_job *sched_job)
} }
} }
/* Update the last fence. */
dma_fence_put(queue->fence_ctx.last_fence);
queue->fence_ctx.last_fence = dma_fence_get(job->done_fence);
done_fence = dma_fence_get(job->done_fence); done_fence = dma_fence_get(job->done_fence);
out_unlock: out_unlock:
...@@ -3378,10 +3395,15 @@ panthor_job_create(struct panthor_file *pfile, ...@@ -3378,10 +3395,15 @@ panthor_job_create(struct panthor_file *pfile,
goto err_put_job; goto err_put_job;
} }
job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL); /* Empty command streams don't need a fence, they'll pick the one from
if (!job->done_fence) { * the previously submitted job.
ret = -ENOMEM; */
goto err_put_job; if (job->call_info.size) {
job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
if (!job->done_fence) {
ret = -ENOMEM;
goto err_put_job;
}
} }
ret = drm_sched_job_init(&job->base, ret = drm_sched_job_init(&job->base,
......
...@@ -346,6 +346,7 @@ static void ttm_bo_release(struct kref *kref) ...@@ -346,6 +346,7 @@ static void ttm_bo_release(struct kref *kref)
if (!dma_resv_test_signaled(bo->base.resv, if (!dma_resv_test_signaled(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP) || DMA_RESV_USAGE_BOOKKEEP) ||
(want_init_on_free() && (bo->ttm != NULL)) || (want_init_on_free() && (bo->ttm != NULL)) ||
bo->type == ttm_bo_type_sg ||
!dma_resv_trylock(bo->base.resv)) { !dma_resv_trylock(bo->base.resv)) {
/* The BO is not idle, resurrect it for delayed destroy */ /* The BO is not idle, resurrect it for delayed destroy */
ttm_bo_flush_all_fences(bo); ttm_bo_flush_all_fences(bo);
......
...@@ -802,6 +802,9 @@ struct drm_panthor_queue_submit { ...@@ -802,6 +802,9 @@ struct drm_panthor_queue_submit {
* Must be 64-bit/8-byte aligned (the size of a CS instruction) * Must be 64-bit/8-byte aligned (the size of a CS instruction)
* *
* Can be zero if stream_addr is zero too. * Can be zero if stream_addr is zero too.
*
* When the stream size is zero, the queue submit serves as a
* synchronization point.
*/ */
__u32 stream_size; __u32 stream_size;
...@@ -822,6 +825,8 @@ struct drm_panthor_queue_submit { ...@@ -822,6 +825,8 @@ struct drm_panthor_queue_submit {
* ensure the GPU doesn't get garbage when reading the indirect command * ensure the GPU doesn't get garbage when reading the indirect command
* stream buffers. If you want the cache flush to happen * stream buffers. If you want the cache flush to happen
* unconditionally, pass a zero here. * unconditionally, pass a zero here.
*
* Ignored when stream_size is zero.
*/ */
__u32 latest_flush; __u32 latest_flush;
......
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