linux/drivers/gpu/drm/i915/gt/intel_timeline.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2016-2018 Intel Corporation
   4 */
   5
   6#include <drm/drm_cache.h>
   7
   8#include "gem/i915_gem_internal.h"
   9
  10#include "i915_active.h"
  11#include "i915_drv.h"
  12#include "i915_syncmap.h"
  13#include "intel_gt.h"
  14#include "intel_ring.h"
  15#include "intel_timeline.h"
  16
  17#define TIMELINE_SEQNO_BYTES 8
  18
  19static struct i915_vma *hwsp_alloc(struct intel_gt *gt)
  20{
  21        struct drm_i915_private *i915 = gt->i915;
  22        struct drm_i915_gem_object *obj;
  23        struct i915_vma *vma;
  24
  25        obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
  26        if (IS_ERR(obj))
  27                return ERR_CAST(obj);
  28
  29        i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
  30
  31        vma = i915_vma_instance(obj, &gt->ggtt->vm, NULL);
  32        if (IS_ERR(vma))
  33                i915_gem_object_put(obj);
  34
  35        return vma;
  36}
  37
  38static void __timeline_retire(struct i915_active *active)
  39{
  40        struct intel_timeline *tl =
  41                container_of(active, typeof(*tl), active);
  42
  43        i915_vma_unpin(tl->hwsp_ggtt);
  44        intel_timeline_put(tl);
  45}
  46
  47static int __timeline_active(struct i915_active *active)
  48{
  49        struct intel_timeline *tl =
  50                container_of(active, typeof(*tl), active);
  51
  52        __i915_vma_pin(tl->hwsp_ggtt);
  53        intel_timeline_get(tl);
  54        return 0;
  55}
  56
  57I915_SELFTEST_EXPORT int
  58intel_timeline_pin_map(struct intel_timeline *timeline)
  59{
  60        struct drm_i915_gem_object *obj = timeline->hwsp_ggtt->obj;
  61        u32 ofs = offset_in_page(timeline->hwsp_offset);
  62        void *vaddr;
  63
  64        vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
  65        if (IS_ERR(vaddr))
  66                return PTR_ERR(vaddr);
  67
  68        timeline->hwsp_map = vaddr;
  69        timeline->hwsp_seqno = memset(vaddr + ofs, 0, TIMELINE_SEQNO_BYTES);
  70        drm_clflush_virt_range(vaddr + ofs, TIMELINE_SEQNO_BYTES);
  71
  72        return 0;
  73}
  74
  75static int intel_timeline_init(struct intel_timeline *timeline,
  76                               struct intel_gt *gt,
  77                               struct i915_vma *hwsp,
  78                               unsigned int offset)
  79{
  80        kref_init(&timeline->kref);
  81        atomic_set(&timeline->pin_count, 0);
  82
  83        timeline->gt = gt;
  84
  85        if (hwsp) {
  86                timeline->hwsp_offset = offset;
  87                timeline->hwsp_ggtt = i915_vma_get(hwsp);
  88        } else {
  89                timeline->has_initial_breadcrumb = true;
  90                hwsp = hwsp_alloc(gt);
  91                if (IS_ERR(hwsp))
  92                        return PTR_ERR(hwsp);
  93                timeline->hwsp_ggtt = hwsp;
  94        }
  95
  96        timeline->hwsp_map = NULL;
  97        timeline->hwsp_seqno = (void *)(long)timeline->hwsp_offset;
  98
  99        GEM_BUG_ON(timeline->hwsp_offset >= hwsp->size);
 100
 101        timeline->fence_context = dma_fence_context_alloc(1);
 102
 103        mutex_init(&timeline->mutex);
 104
 105        INIT_ACTIVE_FENCE(&timeline->last_request);
 106        INIT_LIST_HEAD(&timeline->requests);
 107
 108        i915_syncmap_init(&timeline->sync);
 109        i915_active_init(&timeline->active, __timeline_active,
 110                         __timeline_retire, 0);
 111
 112        return 0;
 113}
 114
 115void intel_gt_init_timelines(struct intel_gt *gt)
 116{
 117        struct intel_gt_timelines *timelines = &gt->timelines;
 118
 119        spin_lock_init(&timelines->lock);
 120        INIT_LIST_HEAD(&timelines->active_list);
 121}
 122
 123static void intel_timeline_fini(struct rcu_head *rcu)
 124{
 125        struct intel_timeline *timeline =
 126                container_of(rcu, struct intel_timeline, rcu);
 127
 128        if (timeline->hwsp_map)
 129                i915_gem_object_unpin_map(timeline->hwsp_ggtt->obj);
 130
 131        i915_vma_put(timeline->hwsp_ggtt);
 132        i915_active_fini(&timeline->active);
 133
 134        /*
 135         * A small race exists between intel_gt_retire_requests_timeout and
 136         * intel_timeline_exit which could result in the syncmap not getting
 137         * free'd. Rather than work to hard to seal this race, simply cleanup
 138         * the syncmap on fini.
 139         */
 140        i915_syncmap_free(&timeline->sync);
 141
 142        kfree(timeline);
 143}
 144
 145struct intel_timeline *
 146__intel_timeline_create(struct intel_gt *gt,
 147                        struct i915_vma *global_hwsp,
 148                        unsigned int offset)
 149{
 150        struct intel_timeline *timeline;
 151        int err;
 152
 153        timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
 154        if (!timeline)
 155                return ERR_PTR(-ENOMEM);
 156
 157        err = intel_timeline_init(timeline, gt, global_hwsp, offset);
 158        if (err) {
 159                kfree(timeline);
 160                return ERR_PTR(err);
 161        }
 162
 163        return timeline;
 164}
 165
 166struct intel_timeline *
 167intel_timeline_create_from_engine(struct intel_engine_cs *engine,
 168                                  unsigned int offset)
 169{
 170        struct i915_vma *hwsp = engine->status_page.vma;
 171        struct intel_timeline *tl;
 172
 173        tl = __intel_timeline_create(engine->gt, hwsp, offset);
 174        if (IS_ERR(tl))
 175                return tl;
 176
 177        /* Borrow a nearby lock; we only create these timelines during init */
 178        mutex_lock(&hwsp->vm->mutex);
 179        list_add_tail(&tl->engine_link, &engine->status_page.timelines);
 180        mutex_unlock(&hwsp->vm->mutex);
 181
 182        return tl;
 183}
 184
 185void __intel_timeline_pin(struct intel_timeline *tl)
 186{
 187        GEM_BUG_ON(!atomic_read(&tl->pin_count));
 188        atomic_inc(&tl->pin_count);
 189}
 190
 191int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww)
 192{
 193        int err;
 194
 195        if (atomic_add_unless(&tl->pin_count, 1, 0))
 196                return 0;
 197
 198        if (!tl->hwsp_map) {
 199                err = intel_timeline_pin_map(tl);
 200                if (err)
 201                        return err;
 202        }
 203
 204        err = i915_ggtt_pin(tl->hwsp_ggtt, ww, 0, PIN_HIGH);
 205        if (err)
 206                return err;
 207
 208        tl->hwsp_offset =
 209                i915_ggtt_offset(tl->hwsp_ggtt) +
 210                offset_in_page(tl->hwsp_offset);
 211        GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
 212                 tl->fence_context, tl->hwsp_offset);
 213
 214        i915_active_acquire(&tl->active);
 215        if (atomic_fetch_inc(&tl->pin_count)) {
 216                i915_active_release(&tl->active);
 217                __i915_vma_unpin(tl->hwsp_ggtt);
 218        }
 219
 220        return 0;
 221}
 222
 223void intel_timeline_reset_seqno(const struct intel_timeline *tl)
 224{
 225        u32 *hwsp_seqno = (u32 *)tl->hwsp_seqno;
 226        /* Must be pinned to be writable, and no requests in flight. */
 227        GEM_BUG_ON(!atomic_read(&tl->pin_count));
 228
 229        memset(hwsp_seqno + 1, 0, TIMELINE_SEQNO_BYTES - sizeof(*hwsp_seqno));
 230        WRITE_ONCE(*hwsp_seqno, tl->seqno);
 231        drm_clflush_virt_range(hwsp_seqno, TIMELINE_SEQNO_BYTES);
 232}
 233
 234void intel_timeline_enter(struct intel_timeline *tl)
 235{
 236        struct intel_gt_timelines *timelines = &tl->gt->timelines;
 237
 238        /*
 239         * Pretend we are serialised by the timeline->mutex.
 240         *
 241         * While generally true, there are a few exceptions to the rule
 242         * for the engine->kernel_context being used to manage power
 243         * transitions. As the engine_park may be called from under any
 244         * timeline, it uses the power mutex as a global serialisation
 245         * lock to prevent any other request entering its timeline.
 246         *
 247         * The rule is generally tl->mutex, otherwise engine->wakeref.mutex.
 248         *
 249         * However, intel_gt_retire_request() does not know which engine
 250         * it is retiring along and so cannot partake in the engine-pm
 251         * barrier, and there we use the tl->active_count as a means to
 252         * pin the timeline in the active_list while the locks are dropped.
 253         * Ergo, as that is outside of the engine-pm barrier, we need to
 254         * use atomic to manipulate tl->active_count.
 255         */
 256        lockdep_assert_held(&tl->mutex);
 257
 258        if (atomic_add_unless(&tl->active_count, 1, 0))
 259                return;
 260
 261        spin_lock(&timelines->lock);
 262        if (!atomic_fetch_inc(&tl->active_count)) {
 263                /*
 264                 * The HWSP is volatile, and may have been lost while inactive,
 265                 * e.g. across suspend/resume. Be paranoid, and ensure that
 266                 * the HWSP value matches our seqno so we don't proclaim
 267                 * the next request as already complete.
 268                 */
 269                intel_timeline_reset_seqno(tl);
 270                list_add_tail(&tl->link, &timelines->active_list);
 271        }
 272        spin_unlock(&timelines->lock);
 273}
 274
 275void intel_timeline_exit(struct intel_timeline *tl)
 276{
 277        struct intel_gt_timelines *timelines = &tl->gt->timelines;
 278
 279        /* See intel_timeline_enter() */
 280        lockdep_assert_held(&tl->mutex);
 281
 282        GEM_BUG_ON(!atomic_read(&tl->active_count));
 283        if (atomic_add_unless(&tl->active_count, -1, 1))
 284                return;
 285
 286        spin_lock(&timelines->lock);
 287        if (atomic_dec_and_test(&tl->active_count))
 288                list_del(&tl->link);
 289        spin_unlock(&timelines->lock);
 290
 291        /*
 292         * Since this timeline is idle, all bariers upon which we were waiting
 293         * must also be complete and so we can discard the last used barriers
 294         * without loss of information.
 295         */
 296        i915_syncmap_free(&tl->sync);
 297}
 298
 299static u32 timeline_advance(struct intel_timeline *tl)
 300{
 301        GEM_BUG_ON(!atomic_read(&tl->pin_count));
 302        GEM_BUG_ON(tl->seqno & tl->has_initial_breadcrumb);
 303
 304        return tl->seqno += 1 + tl->has_initial_breadcrumb;
 305}
 306
 307static noinline int
 308__intel_timeline_get_seqno(struct intel_timeline *tl,
 309                           u32 *seqno)
 310{
 311        u32 next_ofs = offset_in_page(tl->hwsp_offset + TIMELINE_SEQNO_BYTES);
 312
 313        /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
 314        if (TIMELINE_SEQNO_BYTES <= BIT(5) && (next_ofs & BIT(5)))
 315                next_ofs = offset_in_page(next_ofs + BIT(5));
 316
 317        tl->hwsp_offset = i915_ggtt_offset(tl->hwsp_ggtt) + next_ofs;
 318        tl->hwsp_seqno = tl->hwsp_map + next_ofs;
 319        intel_timeline_reset_seqno(tl);
 320
 321        *seqno = timeline_advance(tl);
 322        GEM_BUG_ON(i915_seqno_passed(*tl->hwsp_seqno, *seqno));
 323        return 0;
 324}
 325
 326int intel_timeline_get_seqno(struct intel_timeline *tl,
 327                             struct i915_request *rq,
 328                             u32 *seqno)
 329{
 330        *seqno = timeline_advance(tl);
 331
 332        /* Replace the HWSP on wraparound for HW semaphores */
 333        if (unlikely(!*seqno && tl->has_initial_breadcrumb))
 334                return __intel_timeline_get_seqno(tl, seqno);
 335
 336        return 0;
 337}
 338
 339int intel_timeline_read_hwsp(struct i915_request *from,
 340                             struct i915_request *to,
 341                             u32 *hwsp)
 342{
 343        struct intel_timeline *tl;
 344        int err;
 345
 346        rcu_read_lock();
 347        tl = rcu_dereference(from->timeline);
 348        if (i915_request_signaled(from) ||
 349            !i915_active_acquire_if_busy(&tl->active))
 350                tl = NULL;
 351
 352        if (tl) {
 353                /* hwsp_offset may wraparound, so use from->hwsp_seqno */
 354                *hwsp = i915_ggtt_offset(tl->hwsp_ggtt) +
 355                        offset_in_page(from->hwsp_seqno);
 356        }
 357
 358        /* ensure we wait on the right request, if not, we completed */
 359        if (tl && __i915_request_is_complete(from)) {
 360                i915_active_release(&tl->active);
 361                tl = NULL;
 362        }
 363        rcu_read_unlock();
 364
 365        if (!tl)
 366                return 1;
 367
 368        /* Can't do semaphore waits on kernel context */
 369        if (!tl->has_initial_breadcrumb) {
 370                err = -EINVAL;
 371                goto out;
 372        }
 373
 374        err = i915_active_add_request(&tl->active, to);
 375
 376out:
 377        i915_active_release(&tl->active);
 378        return err;
 379}
 380
 381void intel_timeline_unpin(struct intel_timeline *tl)
 382{
 383        GEM_BUG_ON(!atomic_read(&tl->pin_count));
 384        if (!atomic_dec_and_test(&tl->pin_count))
 385                return;
 386
 387        i915_active_release(&tl->active);
 388        __i915_vma_unpin(tl->hwsp_ggtt);
 389}
 390
 391void __intel_timeline_free(struct kref *kref)
 392{
 393        struct intel_timeline *timeline =
 394                container_of(kref, typeof(*timeline), kref);
 395
 396        GEM_BUG_ON(atomic_read(&timeline->pin_count));
 397        GEM_BUG_ON(!list_empty(&timeline->requests));
 398        GEM_BUG_ON(timeline->retire);
 399
 400        call_rcu(&timeline->rcu, intel_timeline_fini);
 401}
 402
 403void intel_gt_fini_timelines(struct intel_gt *gt)
 404{
 405        struct intel_gt_timelines *timelines = &gt->timelines;
 406
 407        GEM_BUG_ON(!list_empty(&timelines->active_list));
 408}
 409
 410void intel_gt_show_timelines(struct intel_gt *gt,
 411                             struct drm_printer *m,
 412                             void (*show_request)(struct drm_printer *m,
 413                                                  const struct i915_request *rq,
 414                                                  const char *prefix,
 415                                                  int indent))
 416{
 417        struct intel_gt_timelines *timelines = &gt->timelines;
 418        struct intel_timeline *tl, *tn;
 419        LIST_HEAD(free);
 420
 421        spin_lock(&timelines->lock);
 422        list_for_each_entry_safe(tl, tn, &timelines->active_list, link) {
 423                unsigned long count, ready, inflight;
 424                struct i915_request *rq, *rn;
 425                struct dma_fence *fence;
 426
 427                if (!mutex_trylock(&tl->mutex)) {
 428                        drm_printf(m, "Timeline %llx: busy; skipping\n",
 429                                   tl->fence_context);
 430                        continue;
 431                }
 432
 433                intel_timeline_get(tl);
 434                GEM_BUG_ON(!atomic_read(&tl->active_count));
 435                atomic_inc(&tl->active_count); /* pin the list element */
 436                spin_unlock(&timelines->lock);
 437
 438                count = 0;
 439                ready = 0;
 440                inflight = 0;
 441                list_for_each_entry_safe(rq, rn, &tl->requests, link) {
 442                        if (i915_request_completed(rq))
 443                                continue;
 444
 445                        count++;
 446                        if (i915_request_is_ready(rq))
 447                                ready++;
 448                        if (i915_request_is_active(rq))
 449                                inflight++;
 450                }
 451
 452                drm_printf(m, "Timeline %llx: { ", tl->fence_context);
 453                drm_printf(m, "count: %lu, ready: %lu, inflight: %lu",
 454                           count, ready, inflight);
 455                drm_printf(m, ", seqno: { current: %d, last: %d }",
 456                           *tl->hwsp_seqno, tl->seqno);
 457                fence = i915_active_fence_get(&tl->last_request);
 458                if (fence) {
 459                        drm_printf(m, ", engine: %s",
 460                                   to_request(fence)->engine->name);
 461                        dma_fence_put(fence);
 462                }
 463                drm_printf(m, " }\n");
 464
 465                if (show_request) {
 466                        list_for_each_entry_safe(rq, rn, &tl->requests, link)
 467                                show_request(m, rq, "", 2);
 468                }
 469
 470                mutex_unlock(&tl->mutex);
 471                spin_lock(&timelines->lock);
 472
 473                /* Resume list iteration after reacquiring spinlock */
 474                list_safe_reset_next(tl, tn, link);
 475                if (atomic_dec_and_test(&tl->active_count))
 476                        list_del(&tl->link);
 477
 478                /* Defer the final release to after the spinlock */
 479                if (refcount_dec_and_test(&tl->kref.refcount)) {
 480                        GEM_BUG_ON(atomic_read(&tl->active_count));
 481                        list_add(&tl->link, &free);
 482                }
 483        }
 484        spin_unlock(&timelines->lock);
 485
 486        list_for_each_entry_safe(tl, tn, &free, link)
 487                __intel_timeline_free(&tl->kref);
 488}
 489
 490#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 491#include "gt/selftests/mock_timeline.c"
 492#include "gt/selftest_timeline.c"
 493#endif
 494