0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include <linux/pci.h>
0030 #include <linux/vmalloc.h>
0031
0032 #include <drm/radeon_drm.h>
0033 #ifdef CONFIG_X86
0034 #include <asm/set_memory.h>
0035 #endif
0036 #include "radeon.h"
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
0072 {
0073 void *ptr;
0074
0075 ptr = dma_alloc_coherent(&rdev->pdev->dev, rdev->gart.table_size,
0076 &rdev->gart.table_addr, GFP_KERNEL);
0077 if (ptr == NULL) {
0078 return -ENOMEM;
0079 }
0080 #ifdef CONFIG_X86
0081 if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
0082 rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
0083 set_memory_uc((unsigned long)ptr,
0084 rdev->gart.table_size >> PAGE_SHIFT);
0085 }
0086 #endif
0087 rdev->gart.ptr = ptr;
0088 return 0;
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 void radeon_gart_table_ram_free(struct radeon_device *rdev)
0101 {
0102 if (rdev->gart.ptr == NULL) {
0103 return;
0104 }
0105 #ifdef CONFIG_X86
0106 if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
0107 rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
0108 set_memory_wb((unsigned long)rdev->gart.ptr,
0109 rdev->gart.table_size >> PAGE_SHIFT);
0110 }
0111 #endif
0112 dma_free_coherent(&rdev->pdev->dev, rdev->gart.table_size,
0113 (void *)rdev->gart.ptr, rdev->gart.table_addr);
0114 rdev->gart.ptr = NULL;
0115 rdev->gart.table_addr = 0;
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
0129 {
0130 int r;
0131
0132 if (rdev->gart.robj == NULL) {
0133 r = radeon_bo_create(rdev, rdev->gart.table_size,
0134 PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
0135 0, NULL, NULL, &rdev->gart.robj);
0136 if (r) {
0137 return r;
0138 }
0139 }
0140 return 0;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 int radeon_gart_table_vram_pin(struct radeon_device *rdev)
0154 {
0155 uint64_t gpu_addr;
0156 int r;
0157
0158 r = radeon_bo_reserve(rdev->gart.robj, false);
0159 if (unlikely(r != 0))
0160 return r;
0161 r = radeon_bo_pin(rdev->gart.robj,
0162 RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
0163 if (r) {
0164 radeon_bo_unreserve(rdev->gart.robj);
0165 return r;
0166 }
0167 r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
0168 if (r)
0169 radeon_bo_unpin(rdev->gart.robj);
0170 radeon_bo_unreserve(rdev->gart.robj);
0171 rdev->gart.table_addr = gpu_addr;
0172
0173 if (!r) {
0174 int i;
0175
0176
0177
0178
0179 for (i = 0; i < rdev->gart.num_gpu_pages; i++)
0180 radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]);
0181 mb();
0182 radeon_gart_tlb_flush(rdev);
0183 }
0184
0185 return r;
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
0197 {
0198 int r;
0199
0200 if (rdev->gart.robj == NULL) {
0201 return;
0202 }
0203 r = radeon_bo_reserve(rdev->gart.robj, false);
0204 if (likely(r == 0)) {
0205 radeon_bo_kunmap(rdev->gart.robj);
0206 radeon_bo_unpin(rdev->gart.robj);
0207 radeon_bo_unreserve(rdev->gart.robj);
0208 rdev->gart.ptr = NULL;
0209 }
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 void radeon_gart_table_vram_free(struct radeon_device *rdev)
0222 {
0223 if (rdev->gart.robj == NULL) {
0224 return;
0225 }
0226 radeon_bo_unref(&rdev->gart.robj);
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
0243 int pages)
0244 {
0245 unsigned t;
0246 unsigned p;
0247 int i, j;
0248
0249 if (!rdev->gart.ready) {
0250 WARN(1, "trying to unbind memory from uninitialized GART !\n");
0251 return;
0252 }
0253 t = offset / RADEON_GPU_PAGE_SIZE;
0254 p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
0255 for (i = 0; i < pages; i++, p++) {
0256 if (rdev->gart.pages[p]) {
0257 rdev->gart.pages[p] = NULL;
0258 for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
0259 rdev->gart.pages_entry[t] = rdev->dummy_page.entry;
0260 if (rdev->gart.ptr) {
0261 radeon_gart_set_page(rdev, t,
0262 rdev->dummy_page.entry);
0263 }
0264 }
0265 }
0266 }
0267 if (rdev->gart.ptr) {
0268 mb();
0269 radeon_gart_tlb_flush(rdev);
0270 }
0271 }
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
0288 int pages, struct page **pagelist, dma_addr_t *dma_addr,
0289 uint32_t flags)
0290 {
0291 unsigned t;
0292 unsigned p;
0293 uint64_t page_base, page_entry;
0294 int i, j;
0295
0296 if (!rdev->gart.ready) {
0297 WARN(1, "trying to bind memory to uninitialized GART !\n");
0298 return -EINVAL;
0299 }
0300 t = offset / RADEON_GPU_PAGE_SIZE;
0301 p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
0302
0303 for (i = 0; i < pages; i++, p++) {
0304 rdev->gart.pages[p] = pagelist ? pagelist[i] :
0305 rdev->dummy_page.page;
0306 page_base = dma_addr[i];
0307 for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
0308 page_entry = radeon_gart_get_page_entry(page_base, flags);
0309 rdev->gart.pages_entry[t] = page_entry;
0310 if (rdev->gart.ptr) {
0311 radeon_gart_set_page(rdev, t, page_entry);
0312 }
0313 page_base += RADEON_GPU_PAGE_SIZE;
0314 }
0315 }
0316 if (rdev->gart.ptr) {
0317 mb();
0318 radeon_gart_tlb_flush(rdev);
0319 }
0320 return 0;
0321 }
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 int radeon_gart_init(struct radeon_device *rdev)
0332 {
0333 int r, i;
0334
0335 if (rdev->gart.pages) {
0336 return 0;
0337 }
0338
0339 if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) {
0340 DRM_ERROR("Page size is smaller than GPU page size!\n");
0341 return -EINVAL;
0342 }
0343 r = radeon_dummy_page_init(rdev);
0344 if (r)
0345 return r;
0346
0347 rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
0348 rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE;
0349 DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
0350 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
0351
0352 rdev->gart.pages = vzalloc(array_size(sizeof(void *),
0353 rdev->gart.num_cpu_pages));
0354 if (rdev->gart.pages == NULL) {
0355 radeon_gart_fini(rdev);
0356 return -ENOMEM;
0357 }
0358 rdev->gart.pages_entry = vmalloc(array_size(sizeof(uint64_t),
0359 rdev->gart.num_gpu_pages));
0360 if (rdev->gart.pages_entry == NULL) {
0361 radeon_gart_fini(rdev);
0362 return -ENOMEM;
0363 }
0364
0365 for (i = 0; i < rdev->gart.num_gpu_pages; i++)
0366 rdev->gart.pages_entry[i] = rdev->dummy_page.entry;
0367 return 0;
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377 void radeon_gart_fini(struct radeon_device *rdev)
0378 {
0379 if (rdev->gart.ready) {
0380
0381 radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
0382 }
0383 rdev->gart.ready = false;
0384 vfree(rdev->gart.pages);
0385 vfree(rdev->gart.pages_entry);
0386 rdev->gart.pages = NULL;
0387 rdev->gart.pages_entry = NULL;
0388
0389 radeon_dummy_page_fini(rdev);
0390 }