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