Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.2-rc1 351 lines 9.0 kB view raw
1/* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 18 * USE OR OTHER DEALINGS IN THE SOFTWARE. 19 * 20 * The above copyright notice and this permission notice (including the 21 * next paragraph) shall be included in all copies or substantial portions 22 * of the Software. 23 * 24 */ 25/* 26 * Authors: Dave Airlie <airlied@redhat.com> 27 */ 28#include <drm/drmP.h> 29#include <drm/ttm/ttm_page_alloc.h> 30 31#include "mgag200_drv.h" 32 33static inline struct mga_device * 34mgag200_bdev(struct ttm_bo_device *bd) 35{ 36 return container_of(bd, struct mga_device, ttm.bdev); 37} 38 39static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo) 40{ 41 struct mgag200_bo *bo; 42 43 bo = container_of(tbo, struct mgag200_bo, bo); 44 45 drm_gem_object_release(&bo->gem); 46 kfree(bo); 47} 48 49static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo) 50{ 51 if (bo->destroy == &mgag200_bo_ttm_destroy) 52 return true; 53 return false; 54} 55 56static int 57mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, 58 struct ttm_mem_type_manager *man) 59{ 60 switch (type) { 61 case TTM_PL_SYSTEM: 62 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; 63 man->available_caching = TTM_PL_MASK_CACHING; 64 man->default_caching = TTM_PL_FLAG_CACHED; 65 break; 66 case TTM_PL_VRAM: 67 man->func = &ttm_bo_manager_func; 68 man->flags = TTM_MEMTYPE_FLAG_FIXED | 69 TTM_MEMTYPE_FLAG_MAPPABLE; 70 man->available_caching = TTM_PL_FLAG_UNCACHED | 71 TTM_PL_FLAG_WC; 72 man->default_caching = TTM_PL_FLAG_WC; 73 break; 74 default: 75 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); 76 return -EINVAL; 77 } 78 return 0; 79} 80 81static void 82mgag200_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) 83{ 84 struct mgag200_bo *mgabo = mgag200_bo(bo); 85 86 if (!mgag200_ttm_bo_is_mgag200_bo(bo)) 87 return; 88 89 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_SYSTEM); 90 *pl = mgabo->placement; 91} 92 93static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) 94{ 95 struct mgag200_bo *mgabo = mgag200_bo(bo); 96 97 return drm_vma_node_verify_access(&mgabo->gem.vma_node, 98 filp->private_data); 99} 100 101static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev, 102 struct ttm_mem_reg *mem) 103{ 104 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; 105 struct mga_device *mdev = mgag200_bdev(bdev); 106 107 mem->bus.addr = NULL; 108 mem->bus.offset = 0; 109 mem->bus.size = mem->num_pages << PAGE_SHIFT; 110 mem->bus.base = 0; 111 mem->bus.is_iomem = false; 112 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) 113 return -EINVAL; 114 switch (mem->mem_type) { 115 case TTM_PL_SYSTEM: 116 /* system memory */ 117 return 0; 118 case TTM_PL_VRAM: 119 mem->bus.offset = mem->start << PAGE_SHIFT; 120 mem->bus.base = pci_resource_start(mdev->dev->pdev, 0); 121 mem->bus.is_iomem = true; 122 break; 123 default: 124 return -EINVAL; 125 break; 126 } 127 return 0; 128} 129 130static void mgag200_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) 131{ 132} 133 134static void mgag200_ttm_backend_destroy(struct ttm_tt *tt) 135{ 136 ttm_tt_fini(tt); 137 kfree(tt); 138} 139 140static struct ttm_backend_func mgag200_tt_backend_func = { 141 .destroy = &mgag200_ttm_backend_destroy, 142}; 143 144 145static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_buffer_object *bo, 146 uint32_t page_flags) 147{ 148 struct ttm_tt *tt; 149 150 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL); 151 if (tt == NULL) 152 return NULL; 153 tt->func = &mgag200_tt_backend_func; 154 if (ttm_tt_init(tt, bo, page_flags)) { 155 kfree(tt); 156 return NULL; 157 } 158 return tt; 159} 160 161struct ttm_bo_driver mgag200_bo_driver = { 162 .ttm_tt_create = mgag200_ttm_tt_create, 163 .init_mem_type = mgag200_bo_init_mem_type, 164 .eviction_valuable = ttm_bo_eviction_valuable, 165 .evict_flags = mgag200_bo_evict_flags, 166 .move = NULL, 167 .verify_access = mgag200_bo_verify_access, 168 .io_mem_reserve = &mgag200_ttm_io_mem_reserve, 169 .io_mem_free = &mgag200_ttm_io_mem_free, 170}; 171 172int mgag200_mm_init(struct mga_device *mdev) 173{ 174 int ret; 175 struct drm_device *dev = mdev->dev; 176 struct ttm_bo_device *bdev = &mdev->ttm.bdev; 177 178 ret = ttm_bo_device_init(&mdev->ttm.bdev, 179 &mgag200_bo_driver, 180 dev->anon_inode->i_mapping, 181 true); 182 if (ret) { 183 DRM_ERROR("Error initialising bo driver; %d\n", ret); 184 return ret; 185 } 186 187 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, mdev->mc.vram_size >> PAGE_SHIFT); 188 if (ret) { 189 DRM_ERROR("Failed ttm VRAM init: %d\n", ret); 190 return ret; 191 } 192 193 arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), 194 pci_resource_len(dev->pdev, 0)); 195 196 mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0), 197 pci_resource_len(dev->pdev, 0)); 198 199 return 0; 200} 201 202void mgag200_mm_fini(struct mga_device *mdev) 203{ 204 struct drm_device *dev = mdev->dev; 205 206 ttm_bo_device_release(&mdev->ttm.bdev); 207 208 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), 209 pci_resource_len(dev->pdev, 0)); 210 arch_phys_wc_del(mdev->fb_mtrr); 211 mdev->fb_mtrr = 0; 212} 213 214void mgag200_ttm_placement(struct mgag200_bo *bo, int domain) 215{ 216 u32 c = 0; 217 unsigned i; 218 219 bo->placement.placement = bo->placements; 220 bo->placement.busy_placement = bo->placements; 221 if (domain & TTM_PL_FLAG_VRAM) 222 bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; 223 if (domain & TTM_PL_FLAG_SYSTEM) 224 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; 225 if (!c) 226 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; 227 bo->placement.num_placement = c; 228 bo->placement.num_busy_placement = c; 229 for (i = 0; i < c; ++i) { 230 bo->placements[i].fpfn = 0; 231 bo->placements[i].lpfn = 0; 232 } 233} 234 235int mgag200_bo_create(struct drm_device *dev, int size, int align, 236 uint32_t flags, struct mgag200_bo **pmgabo) 237{ 238 struct mga_device *mdev = dev->dev_private; 239 struct mgag200_bo *mgabo; 240 size_t acc_size; 241 int ret; 242 243 mgabo = kzalloc(sizeof(struct mgag200_bo), GFP_KERNEL); 244 if (!mgabo) 245 return -ENOMEM; 246 247 ret = drm_gem_object_init(dev, &mgabo->gem, size); 248 if (ret) { 249 kfree(mgabo); 250 return ret; 251 } 252 253 mgabo->bo.bdev = &mdev->ttm.bdev; 254 255 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); 256 257 acc_size = ttm_bo_dma_acc_size(&mdev->ttm.bdev, size, 258 sizeof(struct mgag200_bo)); 259 260 ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size, 261 ttm_bo_type_device, &mgabo->placement, 262 align >> PAGE_SHIFT, false, acc_size, 263 NULL, NULL, mgag200_bo_ttm_destroy); 264 if (ret) 265 return ret; 266 267 *pmgabo = mgabo; 268 return 0; 269} 270 271static inline u64 mgag200_bo_gpu_offset(struct mgag200_bo *bo) 272{ 273 return bo->bo.offset; 274} 275 276int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr) 277{ 278 struct ttm_operation_ctx ctx = { false, false }; 279 int i, ret; 280 281 if (bo->pin_count) { 282 bo->pin_count++; 283 if (gpu_addr) 284 *gpu_addr = mgag200_bo_gpu_offset(bo); 285 return 0; 286 } 287 288 mgag200_ttm_placement(bo, pl_flag); 289 for (i = 0; i < bo->placement.num_placement; i++) 290 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; 291 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); 292 if (ret) 293 return ret; 294 295 bo->pin_count = 1; 296 if (gpu_addr) 297 *gpu_addr = mgag200_bo_gpu_offset(bo); 298 return 0; 299} 300 301int mgag200_bo_unpin(struct mgag200_bo *bo) 302{ 303 struct ttm_operation_ctx ctx = { false, false }; 304 int i; 305 if (!bo->pin_count) { 306 DRM_ERROR("unpin bad %p\n", bo); 307 return 0; 308 } 309 bo->pin_count--; 310 if (bo->pin_count) 311 return 0; 312 313 for (i = 0; i < bo->placement.num_placement ; i++) 314 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; 315 return ttm_bo_validate(&bo->bo, &bo->placement, &ctx); 316} 317 318int mgag200_bo_push_sysram(struct mgag200_bo *bo) 319{ 320 struct ttm_operation_ctx ctx = { false, false }; 321 int i, ret; 322 if (!bo->pin_count) { 323 DRM_ERROR("unpin bad %p\n", bo); 324 return 0; 325 } 326 bo->pin_count--; 327 if (bo->pin_count) 328 return 0; 329 330 if (bo->kmap.virtual) 331 ttm_bo_kunmap(&bo->kmap); 332 333 mgag200_ttm_placement(bo, TTM_PL_FLAG_SYSTEM); 334 for (i = 0; i < bo->placement.num_placement ; i++) 335 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; 336 337 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); 338 if (ret) { 339 DRM_ERROR("pushing to VRAM failed\n"); 340 return ret; 341 } 342 return 0; 343} 344 345int mgag200_mmap(struct file *filp, struct vm_area_struct *vma) 346{ 347 struct drm_file *file_priv = filp->private_data; 348 struct mga_device *mdev = file_priv->minor->dev->dev_private; 349 350 return ttm_bo_mmap(filp, vma, &mdev->ttm.bdev); 351}