]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge drm/drm-next into drm-misc-next
authorThomas Zimmermann <tzimmermann@suse.de>
Mon, 7 Apr 2025 11:47:40 +0000 (13:47 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Mon, 7 Apr 2025 12:35:48 +0000 (14:35 +0200)
Backmerging to get v6.15-rc1 into drm-misc-next. Also fixes a
build issue when enabling CONFIG_DRM_SCHED_KUNIT_TEST.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
20 files changed:
1  2 
MAINTAINERS
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/bridge/tda998x_drv.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
drivers/gpu/drm/drm_draw.c
drivers/gpu/drm/drm_panic_qr.rs
drivers/gpu/drm/imagination/pvr_fw_meta.c
drivers/gpu/drm/imagination/pvr_fw_trace.c
drivers/gpu/drm/mediatek/mtk_dp.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/msm/dp/dp_ctrl.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/scheduler/tests/mock_scheduler.c
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/vgem/vgem_fence.c

diff --cc MAINTAINERS
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 10b94ac185325b25c9b8757b4c93c558cadf8a78,f2a99681b9985878ae9fdad84bc8896c4718e662..11390cd46dcff35fb275cabed898a41bfbf92c5b
@@@ -873,16 -873,16 +873,16 @@@ impl QrImage<'_> 
  ///
  /// * `url`: The base URL of the QR code. It will be encoded as Binary segment.
  /// * `data`: A pointer to the binary data, to be encoded. if URL is NULL, it
- ///    will be encoded as binary segment, otherwise it will be encoded
- ///    efficiently as a numeric segment, and appended to the URL.
+ ///   will be encoded as binary segment, otherwise it will be encoded
+ ///   efficiently as a numeric segment, and appended to the URL.
  /// * `data_len`: Length of the data, that needs to be encoded, must be less
- ///    than `data_size`.
 -///   than data_size.
++///   than `data_size`.
  /// * `data_size`: Size of data buffer, it should be at least 4071 bytes to hold
- ///    a V40 QR code. It will then be overwritten with the QR code image.
+ ///   a V40 QR code. It will then be overwritten with the QR code image.
  /// * `tmp`: A temporary buffer that the QR code encoder will use, to write the
- ///    segments and ECC.
+ ///   segments and ECC.
  /// * `tmp_size`: Size of the temporary buffer, it must be at least 3706 bytes
- ///    long for V40.
+ ///   long for V40.
  ///
  /// # Safety
  ///
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 61efc96e6e41c322d9cef1f59789076b8ea5762a,0000000000000000000000000000000000000000..f999c8859cf7adb8f06fc8a37969656dd3249fa7
mode 100644,000000..100644
--- /dev/null
@@@ -1,359 -1,0 +1,359 @@@
-       hrtimer_init(&job->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-       job->timer.function = drm_mock_sched_job_signal_timer;
 +// SPDX-License-Identifier: GPL-2.0
 +/* Copyright (c) 2025 Valve Corporation */
 +
 +#include "sched_tests.h"
 +
 +/*
 + * Here we implement the mock "GPU" (or the scheduler backend) which is used by
 + * the DRM scheduler unit tests in order to exercise the core functionality.
 + *
 + * Test cases are implemented in a separate file.
 + */
 +
 +/**
 + * drm_mock_sched_entity_new - Create a new mock scheduler entity
 + *
 + * @test: KUnit test owning the entity
 + * @priority: Scheduling priority
 + * @sched: Mock scheduler on which the entity can be scheduled
 + *
 + * Returns: New mock scheduler entity with allocation managed by the test
 + */
 +struct drm_mock_sched_entity *
 +drm_mock_sched_entity_new(struct kunit *test,
 +                        enum drm_sched_priority priority,
 +                        struct drm_mock_scheduler *sched)
 +{
 +      struct drm_mock_sched_entity *entity;
 +      struct drm_gpu_scheduler *drm_sched;
 +      int ret;
 +
 +      entity = kunit_kzalloc(test, sizeof(*entity), GFP_KERNEL);
 +      KUNIT_ASSERT_NOT_NULL(test, entity);
 +
 +      drm_sched = &sched->base;
 +      ret = drm_sched_entity_init(&entity->base,
 +                                  priority,
 +                                  &drm_sched, 1,
 +                                  NULL);
 +      KUNIT_ASSERT_EQ(test, ret, 0);
 +
 +      entity->test = test;
 +
 +      return entity;
 +}
 +
 +/**
 + * drm_mock_sched_entity_free - Destroys a mock scheduler entity
 + *
 + * @entity: Entity to destroy
 + *
 + * To be used from the test cases once done with the entity.
 + */
 +void drm_mock_sched_entity_free(struct drm_mock_sched_entity *entity)
 +{
 +      drm_sched_entity_destroy(&entity->base);
 +}
 +
 +static void drm_mock_sched_job_complete(struct drm_mock_sched_job *job)
 +{
 +      struct drm_mock_scheduler *sched =
 +              drm_sched_to_mock_sched(job->base.sched);
 +
 +      lockdep_assert_held(&sched->lock);
 +
 +      job->flags |= DRM_MOCK_SCHED_JOB_DONE;
 +      list_move_tail(&job->link, &sched->done_list);
 +      dma_fence_signal(&job->hw_fence);
 +      complete(&job->done);
 +}
 +
 +static enum hrtimer_restart
 +drm_mock_sched_job_signal_timer(struct hrtimer *hrtimer)
 +{
 +      struct drm_mock_sched_job *job =
 +              container_of(hrtimer, typeof(*job), timer);
 +      struct drm_mock_scheduler *sched =
 +              drm_sched_to_mock_sched(job->base.sched);
 +      struct drm_mock_sched_job *next;
 +      ktime_t now = ktime_get();
 +      unsigned long flags;
 +      LIST_HEAD(signal);
 +
 +      spin_lock_irqsave(&sched->lock, flags);
 +      list_for_each_entry_safe(job, next, &sched->job_list, link) {
 +              if (!job->duration_us)
 +                      break;
 +
 +              if (ktime_before(now, job->finish_at))
 +                      break;
 +
 +              sched->hw_timeline.cur_seqno = job->hw_fence.seqno;
 +              drm_mock_sched_job_complete(job);
 +      }
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +
 +      return HRTIMER_NORESTART;
 +}
 +
 +/**
 + * drm_mock_sched_job_new - Create a new mock scheduler job
 + *
 + * @test: KUnit test owning the job
 + * @entity: Scheduler entity of the job
 + *
 + * Returns: New mock scheduler job with allocation managed by the test
 + */
 +struct drm_mock_sched_job *
 +drm_mock_sched_job_new(struct kunit *test,
 +                     struct drm_mock_sched_entity *entity)
 +{
 +      struct drm_mock_sched_job *job;
 +      int ret;
 +
 +      job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
 +      KUNIT_ASSERT_NOT_NULL(test, job);
 +
 +      ret = drm_sched_job_init(&job->base,
 +                               &entity->base,
 +                               1,
 +                               NULL);
 +      KUNIT_ASSERT_EQ(test, ret, 0);
 +
 +      job->test = test;
 +
 +      init_completion(&job->done);
 +      spin_lock_init(&job->lock);
 +      INIT_LIST_HEAD(&job->link);
++      hrtimer_setup(&job->timer, drm_mock_sched_job_signal_timer,
++                    CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 +
 +      return job;
 +}
 +
 +static const char *drm_mock_sched_hw_fence_driver_name(struct dma_fence *fence)
 +{
 +      return "drm_mock_sched";
 +}
 +
 +static const char *
 +drm_mock_sched_hw_fence_timeline_name(struct dma_fence *fence)
 +{
 +      struct drm_mock_sched_job *job =
 +              container_of(fence, typeof(*job), hw_fence);
 +
 +      return (const char *)job->base.sched->name;
 +}
 +
 +static void drm_mock_sched_hw_fence_release(struct dma_fence *fence)
 +{
 +      struct drm_mock_sched_job *job =
 +              container_of(fence, typeof(*job), hw_fence);
 +
 +      hrtimer_cancel(&job->timer);
 +
 +      /* Containing job is freed by the kunit framework */
 +}
 +
 +static const struct dma_fence_ops drm_mock_sched_hw_fence_ops = {
 +      .get_driver_name = drm_mock_sched_hw_fence_driver_name,
 +      .get_timeline_name = drm_mock_sched_hw_fence_timeline_name,
 +      .release = drm_mock_sched_hw_fence_release,
 +};
 +
 +static struct dma_fence *mock_sched_run_job(struct drm_sched_job *sched_job)
 +{
 +      struct drm_mock_scheduler *sched =
 +              drm_sched_to_mock_sched(sched_job->sched);
 +      struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
 +
 +      dma_fence_init(&job->hw_fence,
 +                     &drm_mock_sched_hw_fence_ops,
 +                     &job->lock,
 +                     sched->hw_timeline.context,
 +                     atomic_inc_return(&sched->hw_timeline.next_seqno));
 +
 +      dma_fence_get(&job->hw_fence); /* Reference for the job_list */
 +
 +      spin_lock_irq(&sched->lock);
 +      if (job->duration_us) {
 +              ktime_t prev_finish_at = 0;
 +
 +              if (!list_empty(&sched->job_list)) {
 +                      struct drm_mock_sched_job *prev =
 +                              list_last_entry(&sched->job_list, typeof(*prev),
 +                                              link);
 +
 +                      prev_finish_at = prev->finish_at;
 +              }
 +
 +              if (!prev_finish_at)
 +                      prev_finish_at = ktime_get();
 +
 +              job->finish_at = ktime_add_us(prev_finish_at, job->duration_us);
 +      }
 +      list_add_tail(&job->link, &sched->job_list);
 +      if (job->finish_at)
 +              hrtimer_start(&job->timer, job->finish_at, HRTIMER_MODE_ABS);
 +      spin_unlock_irq(&sched->lock);
 +
 +      return &job->hw_fence;
 +}
 +
 +static enum drm_gpu_sched_stat
 +mock_sched_timedout_job(struct drm_sched_job *sched_job)
 +{
 +      struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
 +
 +      job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
 +
 +      return DRM_GPU_SCHED_STAT_NOMINAL;
 +}
 +
 +static void mock_sched_free_job(struct drm_sched_job *sched_job)
 +{
 +      struct drm_mock_scheduler *sched =
 +                      drm_sched_to_mock_sched(sched_job->sched);
 +      struct drm_mock_sched_job *job = drm_sched_job_to_mock_job(sched_job);
 +      unsigned long flags;
 +
 +      /* Remove from the scheduler done list. */
 +      spin_lock_irqsave(&sched->lock, flags);
 +      list_del(&job->link);
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +      dma_fence_put(&job->hw_fence);
 +
 +      drm_sched_job_cleanup(sched_job);
 +
 +      /* Mock job itself is freed by the kunit framework. */
 +}
 +
 +static const struct drm_sched_backend_ops drm_mock_scheduler_ops = {
 +      .run_job = mock_sched_run_job,
 +      .timedout_job = mock_sched_timedout_job,
 +      .free_job = mock_sched_free_job
 +};
 +
 +/**
 + * drm_mock_sched_new - Create a new mock scheduler
 + *
 + * @test: KUnit test owning the job
 + * @timeout: Job timeout to set
 + *
 + * Returns: New mock scheduler with allocation managed by the test
 + */
 +struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout)
 +{
 +      struct drm_sched_init_args args = {
 +              .ops            = &drm_mock_scheduler_ops,
 +              .num_rqs        = DRM_SCHED_PRIORITY_COUNT,
 +              .credit_limit   = U32_MAX,
 +              .hang_limit     = 1,
 +              .timeout        = timeout,
 +              .name           = "drm-mock-scheduler",
 +      };
 +      struct drm_mock_scheduler *sched;
 +      int ret;
 +
 +      sched = kunit_kzalloc(test, sizeof(*sched), GFP_KERNEL);
 +      KUNIT_ASSERT_NOT_NULL(test, sched);
 +
 +      ret = drm_sched_init(&sched->base, &args);
 +      KUNIT_ASSERT_EQ(test, ret, 0);
 +
 +      sched->test = test;
 +      sched->hw_timeline.context = dma_fence_context_alloc(1);
 +      atomic_set(&sched->hw_timeline.next_seqno, 0);
 +      INIT_LIST_HEAD(&sched->job_list);
 +      INIT_LIST_HEAD(&sched->done_list);
 +      spin_lock_init(&sched->lock);
 +
 +      return sched;
 +}
 +
 +/**
 + * drm_mock_sched_fini - Destroys a mock scheduler
 + *
 + * @sched: Scheduler to destroy
 + *
 + * To be used from the test cases once done with the scheduler.
 + */
 +void drm_mock_sched_fini(struct drm_mock_scheduler *sched)
 +{
 +      struct drm_mock_sched_job *job, *next;
 +      unsigned long flags;
 +      LIST_HEAD(list);
 +
 +      drm_sched_wqueue_stop(&sched->base);
 +
 +      /* Force complete all unfinished jobs. */
 +      spin_lock_irqsave(&sched->lock, flags);
 +      list_for_each_entry_safe(job, next, &sched->job_list, link)
 +              list_move_tail(&job->link, &list);
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +
 +      list_for_each_entry(job, &list, link)
 +              hrtimer_cancel(&job->timer);
 +
 +      spin_lock_irqsave(&sched->lock, flags);
 +      list_for_each_entry_safe(job, next, &list, link)
 +              drm_mock_sched_job_complete(job);
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +
 +      /*
 +       * Free completed jobs and jobs not yet processed by the DRM scheduler
 +       * free worker.
 +       */
 +      spin_lock_irqsave(&sched->lock, flags);
 +      list_for_each_entry_safe(job, next, &sched->done_list, link)
 +              list_move_tail(&job->link, &list);
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +
 +      list_for_each_entry_safe(job, next, &list, link)
 +              mock_sched_free_job(&job->base);
 +
 +      drm_sched_fini(&sched->base);
 +}
 +
 +/**
 + * drm_mock_sched_advance - Advances the mock scheduler timeline
 + *
 + * @sched: Scheduler timeline to advance
 + * @num: By how many jobs to advance
 + *
 + * Advancing the scheduler timeline by a number of seqnos will trigger
 + * signalling of the hardware fences and unlinking the jobs from the internal
 + * scheduler tracking.
 + *
 + * This can be used from test cases which want complete control of the simulated
 + * job execution timing. For example submitting one job with no set duration
 + * would never complete it before test cases advances the timeline by one.
 + */
 +unsigned int drm_mock_sched_advance(struct drm_mock_scheduler *sched,
 +                                  unsigned int num)
 +{
 +      struct drm_mock_sched_job *job, *next;
 +      unsigned int found = 0;
 +      unsigned long flags;
 +      LIST_HEAD(signal);
 +
 +      spin_lock_irqsave(&sched->lock, flags);
 +      if (WARN_ON_ONCE(sched->hw_timeline.cur_seqno + num <
 +                       sched->hw_timeline.cur_seqno))
 +              goto unlock;
 +      sched->hw_timeline.cur_seqno += num;
 +      list_for_each_entry_safe(job, next, &sched->job_list, link) {
 +              if (sched->hw_timeline.cur_seqno < job->hw_fence.seqno)
 +                      break;
 +
 +              drm_mock_sched_job_complete(job);
 +              found++;
 +      }
 +unlock:
 +      spin_unlock_irqrestore(&sched->lock, flags);
 +
 +      return found;
 +}
 +
 +MODULE_DESCRIPTION("DRM mock scheduler and tests");
 +MODULE_LICENSE("GPL");
Simple merge
Simple merge