15718399fSFrançois Tigeot /**************************************************************************
25718399fSFrançois Tigeot *
35718399fSFrançois Tigeot * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
45718399fSFrançois Tigeot * All Rights Reserved.
55718399fSFrançois Tigeot *
65718399fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
75718399fSFrançois Tigeot * copy of this software and associated documentation files (the
85718399fSFrançois Tigeot * "Software"), to deal in the Software without restriction, including
95718399fSFrançois Tigeot * without limitation the rights to use, copy, modify, merge, publish,
105718399fSFrançois Tigeot * distribute, sub license, and/or sell copies of the Software, and to
115718399fSFrançois Tigeot * permit persons to whom the Software is furnished to do so, subject to
125718399fSFrançois Tigeot * the following conditions:
135718399fSFrançois Tigeot *
145718399fSFrançois Tigeot * The above copyright notice and this permission notice (including the
155718399fSFrançois Tigeot * next paragraph) shall be included in all copies or substantial portions
165718399fSFrançois Tigeot * of the Software.
175718399fSFrançois Tigeot *
185718399fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
195718399fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
205718399fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
215718399fSFrançois Tigeot * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
225718399fSFrançois Tigeot * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
235718399fSFrançois Tigeot * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
245718399fSFrançois Tigeot * USE OR OTHER DEALINGS IN THE SOFTWARE.
255718399fSFrançois Tigeot *
265718399fSFrançois Tigeot **************************************************************************/
275718399fSFrançois Tigeot
28216f7a2cSFrançois Tigeot #include <drm/ttm/ttm_execbuf_util.h>
29216f7a2cSFrançois Tigeot #include <drm/ttm/ttm_bo_driver.h>
30216f7a2cSFrançois Tigeot #include <drm/ttm/ttm_placement.h>
31a832fc0dSFrançois Tigeot #include <linux/wait.h>
32fb15202cSFrançois Tigeot #include <linux/sched.h>
33fb15202cSFrançois Tigeot #include <linux/module.h>
345718399fSFrançois Tigeot
ttm_eu_backoff_reservation_reverse(struct list_head * list,struct ttm_validate_buffer * entry)351cfef1a5SFrançois Tigeot static void ttm_eu_backoff_reservation_reverse(struct list_head *list,
361cfef1a5SFrançois Tigeot struct ttm_validate_buffer *entry)
375718399fSFrançois Tigeot {
381cfef1a5SFrançois Tigeot list_for_each_entry_continue_reverse(entry, list, head) {
395718399fSFrançois Tigeot struct ttm_buffer_object *bo = entry->bo;
405718399fSFrançois Tigeot
4143e748b9SFrançois Tigeot __ttm_bo_unreserve(bo);
425718399fSFrançois Tigeot }
434cd92098Szrj }
445718399fSFrançois Tigeot
ttm_eu_del_from_lru_locked(struct list_head * list)455718399fSFrançois Tigeot static void ttm_eu_del_from_lru_locked(struct list_head *list)
465718399fSFrançois Tigeot {
475718399fSFrançois Tigeot struct ttm_validate_buffer *entry;
485718399fSFrançois Tigeot
495718399fSFrançois Tigeot list_for_each_entry(entry, list, head) {
505718399fSFrançois Tigeot struct ttm_buffer_object *bo = entry->bo;
51a85cb24fSFrançois Tigeot ttm_bo_del_from_lru(bo);
525718399fSFrançois Tigeot }
535718399fSFrançois Tigeot }
545718399fSFrançois Tigeot
ttm_eu_backoff_reservation(struct ww_acquire_ctx * ticket,struct list_head * list)554cd92098Szrj void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
564cd92098Szrj struct list_head *list)
575718399fSFrançois Tigeot {
585718399fSFrançois Tigeot struct ttm_validate_buffer *entry;
595718399fSFrançois Tigeot struct ttm_bo_global *glob;
605718399fSFrançois Tigeot
615718399fSFrançois Tigeot if (list_empty(list))
625718399fSFrançois Tigeot return;
635718399fSFrançois Tigeot
645718399fSFrançois Tigeot entry = list_first_entry(list, struct ttm_validate_buffer, head);
65*932d855eSSergey Zigachev glob = entry->bo->bdev->glob;
661cfef1a5SFrançois Tigeot
675718399fSFrançois Tigeot lockmgr(&glob->lru_lock, LK_EXCLUSIVE);
681cfef1a5SFrançois Tigeot list_for_each_entry(entry, list, head) {
691cfef1a5SFrançois Tigeot struct ttm_buffer_object *bo = entry->bo;
701cfef1a5SFrançois Tigeot
711cfef1a5SFrançois Tigeot ttm_bo_add_to_lru(bo);
721cfef1a5SFrançois Tigeot __ttm_bo_unreserve(bo);
731cfef1a5SFrançois Tigeot }
741cfef1a5SFrançois Tigeot lockmgr(&glob->lru_lock, LK_RELEASE);
751cfef1a5SFrançois Tigeot
7643e748b9SFrançois Tigeot if (ticket)
774cd92098Szrj ww_acquire_fini(ticket);
785718399fSFrançois Tigeot }
79c19c6249SFrançois Tigeot EXPORT_SYMBOL(ttm_eu_backoff_reservation);
805718399fSFrançois Tigeot
815718399fSFrançois Tigeot /*
825718399fSFrançois Tigeot * Reserve buffers for validation.
835718399fSFrançois Tigeot *
845718399fSFrançois Tigeot * If a buffer in the list is marked for CPU access, we back off and
855718399fSFrançois Tigeot * wait for that buffer to become free for GPU access.
865718399fSFrançois Tigeot *
875718399fSFrançois Tigeot * If a buffer is reserved for another validation, the validator with
885718399fSFrançois Tigeot * the highest validation sequence backs off and waits for that buffer
895718399fSFrançois Tigeot * to become unreserved. This prevents deadlocks when validating multiple
905718399fSFrançois Tigeot * buffers in different orders.
915718399fSFrançois Tigeot */
925718399fSFrançois Tigeot
ttm_eu_reserve_buffers(struct ww_acquire_ctx * ticket,struct list_head * list,bool intr,struct list_head * dups)934cd92098Szrj int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
947dcf36dcSFrançois Tigeot struct list_head *list, bool intr,
957dcf36dcSFrançois Tigeot struct list_head *dups)
965718399fSFrançois Tigeot {
975718399fSFrançois Tigeot struct ttm_bo_global *glob;
985718399fSFrançois Tigeot struct ttm_validate_buffer *entry;
995718399fSFrançois Tigeot int ret;
1005718399fSFrançois Tigeot
1015718399fSFrançois Tigeot if (list_empty(list))
1025718399fSFrançois Tigeot return 0;
1035718399fSFrançois Tigeot
1045718399fSFrançois Tigeot entry = list_first_entry(list, struct ttm_validate_buffer, head);
105*932d855eSSergey Zigachev glob = entry->bo->bdev->glob;
1065718399fSFrançois Tigeot
10743e748b9SFrançois Tigeot if (ticket)
1084cd92098Szrj ww_acquire_init(ticket, &reservation_ww_class);
1091cfef1a5SFrançois Tigeot
1105718399fSFrançois Tigeot list_for_each_entry(entry, list, head) {
1115718399fSFrançois Tigeot struct ttm_buffer_object *bo = entry->bo;
1125718399fSFrançois Tigeot
113d78d3a22SFrançois Tigeot ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket);
1141cfef1a5SFrançois Tigeot if (!ret && unlikely(atomic_read(&bo->cpu_writers) > 0)) {
1151cfef1a5SFrançois Tigeot __ttm_bo_unreserve(bo);
1161cfef1a5SFrançois Tigeot
1171cfef1a5SFrançois Tigeot ret = -EBUSY;
1187dcf36dcSFrançois Tigeot
1197dcf36dcSFrançois Tigeot } else if (ret == -EALREADY && dups) {
1207dcf36dcSFrançois Tigeot struct ttm_validate_buffer *safe = entry;
1217dcf36dcSFrançois Tigeot entry = list_prev_entry(entry, head);
1227dcf36dcSFrançois Tigeot list_del(&safe->head);
1237dcf36dcSFrançois Tigeot list_add(&safe->head, dups);
1247dcf36dcSFrançois Tigeot continue;
1251cfef1a5SFrançois Tigeot }
1261cfef1a5SFrançois Tigeot
1271cfef1a5SFrançois Tigeot if (!ret) {
1281cfef1a5SFrançois Tigeot if (!entry->shared)
1296f486c69SFrançois Tigeot continue;
1306f486c69SFrançois Tigeot
1311cfef1a5SFrançois Tigeot ret = reservation_object_reserve_shared(bo->resv);
1321cfef1a5SFrançois Tigeot if (!ret)
1331cfef1a5SFrançois Tigeot continue;
1341cfef1a5SFrançois Tigeot }
1353c3b358eSFrançois Tigeot
1363c3b358eSFrançois Tigeot /* uh oh, we lost out, drop every reservation and try
1373c3b358eSFrançois Tigeot * to only reserve this buffer, then start over if
1383c3b358eSFrançois Tigeot * this succeeds.
1393c3b358eSFrançois Tigeot */
1401cfef1a5SFrançois Tigeot ttm_eu_backoff_reservation_reverse(list, entry);
1411cfef1a5SFrançois Tigeot
1421cfef1a5SFrançois Tigeot if (ret == -EDEADLK && intr) {
1433c3b358eSFrançois Tigeot ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
1443c3b358eSFrançois Tigeot ticket);
1451cfef1a5SFrançois Tigeot } else if (ret == -EDEADLK) {
1461cfef1a5SFrançois Tigeot ww_mutex_lock_slow(&bo->resv->lock, ticket);
1471cfef1a5SFrançois Tigeot ret = 0;
1481cfef1a5SFrançois Tigeot }
1491cfef1a5SFrançois Tigeot
1501cfef1a5SFrançois Tigeot if (!ret && entry->shared)
1511cfef1a5SFrançois Tigeot ret = reservation_object_reserve_shared(bo->resv);
1521cfef1a5SFrançois Tigeot
1533c3b358eSFrançois Tigeot if (unlikely(ret != 0)) {
1543c3b358eSFrançois Tigeot if (ret == -EINTR)
1553c3b358eSFrançois Tigeot ret = -ERESTARTSYS;
1561cfef1a5SFrançois Tigeot if (ticket) {
1571cfef1a5SFrançois Tigeot ww_acquire_done(ticket);
1581cfef1a5SFrançois Tigeot ww_acquire_fini(ticket);
1591cfef1a5SFrançois Tigeot }
1601cfef1a5SFrançois Tigeot return ret;
1613c3b358eSFrançois Tigeot }
1624cd92098Szrj
1631cfef1a5SFrançois Tigeot /* move this item to the front of the list,
1641cfef1a5SFrançois Tigeot * forces correct iteration of the loop without keeping track
1651cfef1a5SFrançois Tigeot */
1661cfef1a5SFrançois Tigeot list_del(&entry->head);
1671cfef1a5SFrançois Tigeot list_add(&entry->head, list);
1685718399fSFrançois Tigeot }
1695718399fSFrançois Tigeot
17043e748b9SFrançois Tigeot if (ticket)
1714cd92098Szrj ww_acquire_done(ticket);
1723c3b358eSFrançois Tigeot lockmgr(&glob->lru_lock, LK_EXCLUSIVE);
1735718399fSFrançois Tigeot ttm_eu_del_from_lru_locked(list);
1745718399fSFrançois Tigeot lockmgr(&glob->lru_lock, LK_RELEASE);
1755718399fSFrançois Tigeot return 0;
1765718399fSFrançois Tigeot }
177c19c6249SFrançois Tigeot EXPORT_SYMBOL(ttm_eu_reserve_buffers);
1785718399fSFrançois Tigeot
ttm_eu_fence_buffer_objects(struct ww_acquire_ctx * ticket,struct list_head * list,struct dma_fence * fence)1794cd92098Szrj void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
1806559babbSFrançois Tigeot struct list_head *list,
1816559babbSFrançois Tigeot struct dma_fence *fence)
1825718399fSFrançois Tigeot {
1835718399fSFrançois Tigeot struct ttm_validate_buffer *entry;
1845718399fSFrançois Tigeot struct ttm_buffer_object *bo;
1855718399fSFrançois Tigeot struct ttm_bo_global *glob;
1865718399fSFrançois Tigeot struct ttm_bo_device *bdev;
1875718399fSFrançois Tigeot struct ttm_bo_driver *driver;
1885718399fSFrançois Tigeot
1895718399fSFrançois Tigeot if (list_empty(list))
1905718399fSFrançois Tigeot return;
1915718399fSFrançois Tigeot
1925718399fSFrançois Tigeot bo = list_first_entry(list, struct ttm_validate_buffer, head)->bo;
1935718399fSFrançois Tigeot bdev = bo->bdev;
1945718399fSFrançois Tigeot driver = bdev->driver;
195*932d855eSSergey Zigachev glob = bo->bdev->glob;
1965718399fSFrançois Tigeot
1975718399fSFrançois Tigeot lockmgr(&glob->lru_lock, LK_EXCLUSIVE);
1985718399fSFrançois Tigeot
1995718399fSFrançois Tigeot list_for_each_entry(entry, list, head) {
2005718399fSFrançois Tigeot bo = entry->bo;
2011cfef1a5SFrançois Tigeot if (entry->shared)
2021cfef1a5SFrançois Tigeot reservation_object_add_shared_fence(bo->resv, fence);
2031cfef1a5SFrançois Tigeot else
2041cfef1a5SFrançois Tigeot reservation_object_add_excl_fence(bo->resv, fence);
2056a001295SFrançois Tigeot ttm_bo_add_to_lru(bo);
20643e748b9SFrançois Tigeot __ttm_bo_unreserve(bo);
2075718399fSFrançois Tigeot }
2085718399fSFrançois Tigeot lockmgr(&glob->lru_lock, LK_RELEASE);
20943e748b9SFrançois Tigeot if (ticket)
2104cd92098Szrj ww_acquire_fini(ticket);
2115718399fSFrançois Tigeot }
212c19c6249SFrançois Tigeot EXPORT_SYMBOL(ttm_eu_fence_buffer_objects);
213