11.2Sriastrad/* $NetBSD: ttm_agp_backend.c,v 1.3 2021/12/18 23:45:44 riastradh Exp $ */ 21.2Sriastrad 31.3Sriastrad/* SPDX-License-Identifier: GPL-2.0 OR MIT */ 41.1Sriastrad/************************************************************************** 51.1Sriastrad * 61.1Sriastrad * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA 71.1Sriastrad * All Rights Reserved. 81.1Sriastrad * 91.1Sriastrad * Permission is hereby granted, free of charge, to any person obtaining a 101.1Sriastrad * copy of this software and associated documentation files (the 111.1Sriastrad * "Software"), to deal in the Software without restriction, including 121.1Sriastrad * without limitation the rights to use, copy, modify, merge, publish, 131.1Sriastrad * distribute, sub license, and/or sell copies of the Software, and to 141.1Sriastrad * permit persons to whom the Software is furnished to do so, subject to 151.1Sriastrad * the following conditions: 161.1Sriastrad * 171.1Sriastrad * The above copyright notice and this permission notice (including the 181.1Sriastrad * next paragraph) shall be included in all copies or substantial portions 191.1Sriastrad * of the Software. 201.1Sriastrad * 211.1Sriastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 221.1Sriastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 231.1Sriastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 241.1Sriastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 251.1Sriastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 261.1Sriastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 271.1Sriastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 281.1Sriastrad * 291.1Sriastrad **************************************************************************/ 301.1Sriastrad/* 311.1Sriastrad * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 321.1Sriastrad * Keith Packard. 331.1Sriastrad */ 341.1Sriastrad 351.2Sriastrad#include <sys/cdefs.h> 361.2Sriastrad__KERNEL_RCSID(0, "$NetBSD: ttm_agp_backend.c,v 1.3 2021/12/18 23:45:44 riastradh Exp $"); 371.2Sriastrad 381.1Sriastrad#define pr_fmt(fmt) "[TTM] " fmt 391.1Sriastrad 401.1Sriastrad#include <drm/ttm/ttm_module.h> 411.1Sriastrad#include <drm/ttm/ttm_bo_driver.h> 421.1Sriastrad#include <drm/ttm/ttm_page_alloc.h> 431.1Sriastrad#include <drm/ttm/ttm_placement.h> 441.1Sriastrad#include <linux/agp_backend.h> 451.1Sriastrad#include <linux/module.h> 461.1Sriastrad#include <linux/slab.h> 471.1Sriastrad#include <linux/io.h> 481.1Sriastrad#include <asm/agp.h> 491.1Sriastrad 501.1Sriastradstruct ttm_agp_backend { 511.1Sriastrad struct ttm_tt ttm; 521.1Sriastrad struct agp_memory *mem; 531.1Sriastrad struct agp_bridge_data *bridge; 541.1Sriastrad}; 551.1Sriastrad 561.1Sriastradstatic int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) 571.1Sriastrad{ 581.1Sriastrad struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); 591.3Sriastrad struct page *dummy_read_page = ttm_bo_glob.dummy_read_page; 601.1Sriastrad struct drm_mm_node *node = bo_mem->mm_node; 611.1Sriastrad struct agp_memory *mem; 621.1Sriastrad int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); 631.1Sriastrad unsigned i; 641.1Sriastrad 651.1Sriastrad mem = agp_allocate_memory(agp_be->bridge, ttm->num_pages, AGP_USER_MEMORY); 661.1Sriastrad if (unlikely(mem == NULL)) 671.1Sriastrad return -ENOMEM; 681.1Sriastrad 691.1Sriastrad mem->page_count = 0; 701.1Sriastrad for (i = 0; i < ttm->num_pages; i++) { 711.1Sriastrad struct page *page = ttm->pages[i]; 721.1Sriastrad 731.1Sriastrad if (!page) 741.3Sriastrad page = dummy_read_page; 751.1Sriastrad 761.1Sriastrad mem->pages[mem->page_count++] = page; 771.1Sriastrad } 781.1Sriastrad agp_be->mem = mem; 791.1Sriastrad 801.1Sriastrad mem->is_flushed = 1; 811.1Sriastrad mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; 821.1Sriastrad 831.1Sriastrad ret = agp_bind_memory(mem, node->start); 841.1Sriastrad if (ret) 851.1Sriastrad pr_err("AGP Bind memory failed\n"); 861.1Sriastrad 871.1Sriastrad return ret; 881.1Sriastrad} 891.1Sriastrad 901.1Sriastradstatic int ttm_agp_unbind(struct ttm_tt *ttm) 911.1Sriastrad{ 921.1Sriastrad struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); 931.1Sriastrad 941.1Sriastrad if (agp_be->mem) { 951.1Sriastrad if (agp_be->mem->is_bound) 961.1Sriastrad return agp_unbind_memory(agp_be->mem); 971.1Sriastrad agp_free_memory(agp_be->mem); 981.1Sriastrad agp_be->mem = NULL; 991.1Sriastrad } 1001.1Sriastrad return 0; 1011.1Sriastrad} 1021.1Sriastrad 1031.1Sriastradstatic void ttm_agp_destroy(struct ttm_tt *ttm) 1041.1Sriastrad{ 1051.1Sriastrad struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); 1061.1Sriastrad 1071.1Sriastrad if (agp_be->mem) 1081.1Sriastrad ttm_agp_unbind(ttm); 1091.1Sriastrad ttm_tt_fini(ttm); 1101.1Sriastrad kfree(agp_be); 1111.1Sriastrad} 1121.1Sriastrad 1131.1Sriastradstatic struct ttm_backend_func ttm_agp_func = { 1141.1Sriastrad .bind = ttm_agp_bind, 1151.1Sriastrad .unbind = ttm_agp_unbind, 1161.1Sriastrad .destroy = ttm_agp_destroy, 1171.1Sriastrad}; 1181.1Sriastrad 1191.3Sriastradstruct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, 1201.1Sriastrad struct agp_bridge_data *bridge, 1211.3Sriastrad uint32_t page_flags) 1221.1Sriastrad{ 1231.1Sriastrad struct ttm_agp_backend *agp_be; 1241.1Sriastrad 1251.1Sriastrad agp_be = kmalloc(sizeof(*agp_be), GFP_KERNEL); 1261.1Sriastrad if (!agp_be) 1271.1Sriastrad return NULL; 1281.1Sriastrad 1291.1Sriastrad agp_be->mem = NULL; 1301.1Sriastrad agp_be->bridge = bridge; 1311.1Sriastrad agp_be->ttm.func = &ttm_agp_func; 1321.1Sriastrad 1331.3Sriastrad if (ttm_tt_init(&agp_be->ttm, bo, page_flags)) { 1341.2Sriastrad kfree(agp_be); 1351.1Sriastrad return NULL; 1361.1Sriastrad } 1371.1Sriastrad 1381.1Sriastrad return &agp_be->ttm; 1391.1Sriastrad} 1401.1SriastradEXPORT_SYMBOL(ttm_agp_tt_create); 1411.1Sriastrad 1421.3Sriastradint ttm_agp_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) 1431.1Sriastrad{ 1441.1Sriastrad if (ttm->state != tt_unpopulated) 1451.1Sriastrad return 0; 1461.1Sriastrad 1471.3Sriastrad return ttm_pool_populate(ttm, ctx); 1481.1Sriastrad} 1491.1SriastradEXPORT_SYMBOL(ttm_agp_tt_populate); 1501.1Sriastrad 1511.1Sriastradvoid ttm_agp_tt_unpopulate(struct ttm_tt *ttm) 1521.1Sriastrad{ 1531.1Sriastrad ttm_pool_unpopulate(ttm); 1541.1Sriastrad} 1551.1SriastradEXPORT_SYMBOL(ttm_agp_tt_unpopulate); 156