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

drm/i915: add GEM GTT mapping support

Use the new core GEM object mapping code to allow GTT mapping of GEM
objects on i915. The fault handler will make sure a fence register is
allocated too, if the object in question is tiled.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Jesse Barnes and committed by
Dave Airlie
de151cf6 a2c0a97b

+562 -4
+1
drivers/gpu/drm/i915/i915_dma.c
··· 991 991 DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), 992 992 DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), 993 993 DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), 994 + DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0), 994 995 DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), 995 996 DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), 996 997 DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
+6 -1
drivers/gpu/drm/i915/i915_drv.c
··· 81 81 return 0; 82 82 } 83 83 84 + static struct vm_operations_struct i915_gem_vm_ops = { 85 + .fault = i915_gem_fault, 86 + }; 87 + 84 88 static struct drm_driver driver = { 85 89 /* don't use mtrr's here, the Xserver or user space app should 86 90 * deal with them for intel hardware. ··· 117 113 .proc_cleanup = i915_gem_proc_cleanup, 118 114 .gem_init_object = i915_gem_init_object, 119 115 .gem_free_object = i915_gem_free_object, 116 + .gem_vm_ops = &i915_gem_vm_ops, 120 117 .ioctls = i915_ioctls, 121 118 .fops = { 122 119 .owner = THIS_MODULE, 123 120 .open = drm_open, 124 121 .release = drm_release, 125 122 .ioctl = drm_ioctl, 126 - .mmap = drm_mmap, 123 + .mmap = drm_gem_mmap, 127 124 .poll = drm_poll, 128 125 .fasync = drm_fasync, 129 126 #ifdef CONFIG_COMPAT
+35
drivers/gpu/drm/i915/i915_drv.h
··· 107 107 drm_local_map_t *sarea; 108 108 struct _drm_i915_sarea *sarea_priv; 109 109 }; 110 + #define I915_FENCE_REG_NONE -1 111 + 112 + struct drm_i915_fence_reg { 113 + struct drm_gem_object *obj; 114 + }; 110 115 111 116 typedef struct drm_i915_private { 112 117 struct drm_device *dev; ··· 153 148 int vblank_pipe; 154 149 155 150 struct intel_opregion opregion; 151 + 152 + struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ 153 + int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ 154 + int num_fence_regs; /* 8 on pre-965, 16 otherwise */ 156 155 157 156 /* Register state */ 158 157 u8 saveLBB; ··· 376 367 * This is the same as gtt_space->start 377 368 */ 378 369 uint32_t gtt_offset; 370 + /** 371 + * Required alignment for the object 372 + */ 373 + uint32_t gtt_alignment; 374 + /** 375 + * Fake offset for use by mmap(2) 376 + */ 377 + uint64_t mmap_offset; 378 + 379 + /** 380 + * Fence register bits (if any) for this object. Will be set 381 + * as needed when mapped into the GTT. 382 + * Protected by dev->struct_mutex. 383 + */ 384 + int fence_reg; 379 385 380 386 /** Boolean whether this object has a valid gtt offset. */ 381 387 int gtt_bound; ··· 403 379 404 380 /** Current tiling mode for the object. */ 405 381 uint32_t tiling_mode; 382 + uint32_t stride; 406 383 407 384 /** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */ 408 385 uint32_t agp_type; ··· 518 493 struct drm_file *file_priv); 519 494 int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, 520 495 struct drm_file *file_priv); 496 + int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, 497 + struct drm_file *file_priv); 521 498 int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, 522 499 struct drm_file *file_priv); 523 500 int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, ··· 556 529 void i915_gem_retire_requests(struct drm_device *dev); 557 530 void i915_gem_retire_work_handler(struct work_struct *work); 558 531 void i915_gem_clflush_object(struct drm_gem_object *obj); 532 + int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 559 533 560 534 /* i915_gem_tiling.c */ 561 535 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); ··· 612 584 #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) 613 585 #define I915_READ8(reg) readb(dev_priv->regs + (reg)) 614 586 #define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg)) 587 + #ifdef writeq 588 + #define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg)) 589 + #else 590 + #define I915_WRITE64(reg, val) (writel(val, dev_priv->regs + (reg)), \ 591 + writel(upper_32_bits(val), dev_priv->regs + \ 592 + (reg) + 4)) 593 + #endif 615 594 616 595 #define I915_VERBOSE 0 617 596
+486 -2
drivers/gpu/drm/i915/i915_gem.c
··· 51 51 static int i915_gem_object_get_page_list(struct drm_gem_object *obj); 52 52 static void i915_gem_object_free_page_list(struct drm_gem_object *obj); 53 53 static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); 54 + static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, 55 + unsigned alignment); 56 + static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj); 57 + static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); 58 + static int i915_gem_evict_something(struct drm_device *dev); 54 59 55 60 static void 56 61 i915_gem_cleanup_ringbuffer(struct drm_device *dev); ··· 534 529 return 0; 535 530 } 536 531 532 + /** 533 + * i915_gem_fault - fault a page into the GTT 534 + * vma: VMA in question 535 + * vmf: fault info 536 + * 537 + * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped 538 + * from userspace. The fault handler takes care of binding the object to 539 + * the GTT (if needed), allocating and programming a fence register (again, 540 + * only if needed based on whether the old reg is still valid or the object 541 + * is tiled) and inserting a new PTE into the faulting process. 542 + * 543 + * Note that the faulting process may involve evicting existing objects 544 + * from the GTT and/or fence registers to make room. So performance may 545 + * suffer if the GTT working set is large or there are few fence registers 546 + * left. 547 + */ 548 + int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 549 + { 550 + struct drm_gem_object *obj = vma->vm_private_data; 551 + struct drm_device *dev = obj->dev; 552 + struct drm_i915_private *dev_priv = dev->dev_private; 553 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 554 + pgoff_t page_offset; 555 + unsigned long pfn; 556 + int ret = 0; 557 + 558 + /* We don't use vmf->pgoff since that has the fake offset */ 559 + page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> 560 + PAGE_SHIFT; 561 + 562 + /* Now bind it into the GTT if needed */ 563 + mutex_lock(&dev->struct_mutex); 564 + if (!obj_priv->gtt_space) { 565 + ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment); 566 + if (ret) { 567 + mutex_unlock(&dev->struct_mutex); 568 + return VM_FAULT_SIGBUS; 569 + } 570 + list_add(&obj_priv->list, &dev_priv->mm.inactive_list); 571 + } 572 + 573 + /* Need a new fence register? */ 574 + if (obj_priv->fence_reg == I915_FENCE_REG_NONE && 575 + obj_priv->tiling_mode != I915_TILING_NONE) 576 + i915_gem_object_get_fence_reg(obj); 577 + 578 + pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + 579 + page_offset; 580 + 581 + /* Finally, remap it using the new GTT offset */ 582 + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); 583 + 584 + mutex_unlock(&dev->struct_mutex); 585 + 586 + switch (ret) { 587 + case -ENOMEM: 588 + case -EAGAIN: 589 + return VM_FAULT_OOM; 590 + case -EFAULT: 591 + case -EBUSY: 592 + DRM_ERROR("can't insert pfn?? fault or busy...\n"); 593 + return VM_FAULT_SIGBUS; 594 + default: 595 + return VM_FAULT_NOPAGE; 596 + } 597 + } 598 + 599 + /** 600 + * i915_gem_create_mmap_offset - create a fake mmap offset for an object 601 + * @obj: obj in question 602 + * 603 + * GEM memory mapping works by handing back to userspace a fake mmap offset 604 + * it can use in a subsequent mmap(2) call. The DRM core code then looks 605 + * up the object based on the offset and sets up the various memory mapping 606 + * structures. 607 + * 608 + * This routine allocates and attaches a fake offset for @obj. 609 + */ 610 + static int 611 + i915_gem_create_mmap_offset(struct drm_gem_object *obj) 612 + { 613 + struct drm_device *dev = obj->dev; 614 + struct drm_gem_mm *mm = dev->mm_private; 615 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 616 + struct drm_map_list *list; 617 + struct drm_map *map; 618 + int ret = 0; 619 + 620 + /* Set the object up for mmap'ing */ 621 + list = &obj->map_list; 622 + list->map = drm_calloc(1, sizeof(struct drm_map_list), 623 + DRM_MEM_DRIVER); 624 + if (!list->map) 625 + return -ENOMEM; 626 + 627 + map = list->map; 628 + map->type = _DRM_GEM; 629 + map->size = obj->size; 630 + map->handle = obj; 631 + 632 + /* Get a DRM GEM mmap offset allocated... */ 633 + list->file_offset_node = drm_mm_search_free(&mm->offset_manager, 634 + obj->size / PAGE_SIZE, 0, 0); 635 + if (!list->file_offset_node) { 636 + DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); 637 + ret = -ENOMEM; 638 + goto out_free_list; 639 + } 640 + 641 + list->file_offset_node = drm_mm_get_block(list->file_offset_node, 642 + obj->size / PAGE_SIZE, 0); 643 + if (!list->file_offset_node) { 644 + ret = -ENOMEM; 645 + goto out_free_list; 646 + } 647 + 648 + list->hash.key = list->file_offset_node->start; 649 + if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { 650 + DRM_ERROR("failed to add to map hash\n"); 651 + goto out_free_mm; 652 + } 653 + 654 + /* By now we should be all set, any drm_mmap request on the offset 655 + * below will get to our mmap & fault handler */ 656 + obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT; 657 + 658 + return 0; 659 + 660 + out_free_mm: 661 + drm_mm_put_block(list->file_offset_node); 662 + out_free_list: 663 + drm_free(list->map, sizeof(struct drm_map_list), DRM_MEM_DRIVER); 664 + 665 + return ret; 666 + } 667 + 668 + /** 669 + * i915_gem_get_gtt_alignment - return required GTT alignment for an object 670 + * @obj: object to check 671 + * 672 + * Return the required GTT alignment for an object, taking into account 673 + * potential fence register mapping if needed. 674 + */ 675 + static uint32_t 676 + i915_gem_get_gtt_alignment(struct drm_gem_object *obj) 677 + { 678 + struct drm_device *dev = obj->dev; 679 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 680 + int start, i; 681 + 682 + /* 683 + * Minimum alignment is 4k (GTT page size), but might be greater 684 + * if a fence register is needed for the object. 685 + */ 686 + if (IS_I965G(dev) || obj_priv->tiling_mode == I915_TILING_NONE) 687 + return 4096; 688 + 689 + /* 690 + * Previous chips need to be aligned to the size of the smallest 691 + * fence register that can contain the object. 692 + */ 693 + if (IS_I9XX(dev)) 694 + start = 1024*1024; 695 + else 696 + start = 512*1024; 697 + 698 + for (i = start; i < obj->size; i <<= 1) 699 + ; 700 + 701 + return i; 702 + } 703 + 704 + /** 705 + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing 706 + * @dev: DRM device 707 + * @data: GTT mapping ioctl data 708 + * @file_priv: GEM object info 709 + * 710 + * Simply returns the fake offset to userspace so it can mmap it. 711 + * The mmap call will end up in drm_gem_mmap(), which will set things 712 + * up so we can get faults in the handler above. 713 + * 714 + * The fault handler will take care of binding the object into the GTT 715 + * (since it may have been evicted to make room for something), allocating 716 + * a fence register, and mapping the appropriate aperture address into 717 + * userspace. 718 + */ 719 + int 720 + i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, 721 + struct drm_file *file_priv) 722 + { 723 + struct drm_i915_gem_mmap_gtt *args = data; 724 + struct drm_i915_private *dev_priv = dev->dev_private; 725 + struct drm_gem_object *obj; 726 + struct drm_i915_gem_object *obj_priv; 727 + int ret; 728 + 729 + if (!(dev->driver->driver_features & DRIVER_GEM)) 730 + return -ENODEV; 731 + 732 + obj = drm_gem_object_lookup(dev, file_priv, args->handle); 733 + if (obj == NULL) 734 + return -EBADF; 735 + 736 + mutex_lock(&dev->struct_mutex); 737 + 738 + obj_priv = obj->driver_private; 739 + 740 + if (!obj_priv->mmap_offset) { 741 + ret = i915_gem_create_mmap_offset(obj); 742 + if (ret) 743 + return ret; 744 + } 745 + 746 + args->offset = obj_priv->mmap_offset; 747 + 748 + obj_priv->gtt_alignment = i915_gem_get_gtt_alignment(obj); 749 + 750 + /* Make sure the alignment is correct for fence regs etc */ 751 + if (obj_priv->agp_mem && 752 + (obj_priv->gtt_offset & (obj_priv->gtt_alignment - 1))) { 753 + drm_gem_object_unreference(obj); 754 + mutex_unlock(&dev->struct_mutex); 755 + return -EINVAL; 756 + } 757 + 758 + /* 759 + * Pull it into the GTT so that we have a page list (makes the 760 + * initial fault faster and any subsequent flushing possible). 761 + */ 762 + if (!obj_priv->agp_mem) { 763 + ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment); 764 + if (ret) { 765 + drm_gem_object_unreference(obj); 766 + mutex_unlock(&dev->struct_mutex); 767 + return ret; 768 + } 769 + list_add(&obj_priv->list, &dev_priv->mm.inactive_list); 770 + } 771 + 772 + drm_gem_object_unreference(obj); 773 + mutex_unlock(&dev->struct_mutex); 774 + 775 + return 0; 776 + } 777 + 537 778 static void 538 779 i915_gem_object_free_page_list(struct drm_gem_object *obj) 539 780 { ··· 977 726 */ 978 727 if (obj_priv->last_rendering_seqno != request->seqno) 979 728 return; 729 + 980 730 #if WATCH_LRU 981 731 DRM_INFO("%s: retire %d moves to inactive list %p\n", 982 732 __func__, request->seqno, obj); ··· 1208 956 { 1209 957 struct drm_device *dev = obj->dev; 1210 958 struct drm_i915_gem_object *obj_priv = obj->driver_private; 959 + loff_t offset; 1211 960 int ret = 0; 1212 961 1213 962 #if WATCH_BUF ··· 1243 990 } 1244 991 1245 992 BUG_ON(obj_priv->active); 993 + 994 + /* blow away mappings if mapped through GTT */ 995 + offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; 996 + unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); 997 + 998 + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) 999 + i915_gem_clear_fence_reg(obj); 1246 1000 1247 1001 i915_gem_object_free_page_list(obj); 1248 1002 ··· 1407 1147 obj_priv->page_list[i] = page; 1408 1148 } 1409 1149 return 0; 1150 + } 1151 + 1152 + static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) 1153 + { 1154 + struct drm_gem_object *obj = reg->obj; 1155 + struct drm_device *dev = obj->dev; 1156 + drm_i915_private_t *dev_priv = dev->dev_private; 1157 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 1158 + int regnum = obj_priv->fence_reg; 1159 + uint64_t val; 1160 + 1161 + val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) & 1162 + 0xfffff000) << 32; 1163 + val |= obj_priv->gtt_offset & 0xfffff000; 1164 + val |= ((obj_priv->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT; 1165 + if (obj_priv->tiling_mode == I915_TILING_Y) 1166 + val |= 1 << I965_FENCE_TILING_Y_SHIFT; 1167 + val |= I965_FENCE_REG_VALID; 1168 + 1169 + I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val); 1170 + } 1171 + 1172 + static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) 1173 + { 1174 + struct drm_gem_object *obj = reg->obj; 1175 + struct drm_device *dev = obj->dev; 1176 + drm_i915_private_t *dev_priv = dev->dev_private; 1177 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 1178 + int regnum = obj_priv->fence_reg; 1179 + uint32_t val; 1180 + uint32_t pitch_val; 1181 + 1182 + if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || 1183 + (obj_priv->gtt_offset & (obj->size - 1))) { 1184 + WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__); 1185 + return; 1186 + } 1187 + 1188 + if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) || 1189 + IS_I945GM(dev) || 1190 + IS_G33(dev))) 1191 + pitch_val = (obj_priv->stride / 128) - 1; 1192 + else 1193 + pitch_val = (obj_priv->stride / 512) - 1; 1194 + 1195 + val = obj_priv->gtt_offset; 1196 + if (obj_priv->tiling_mode == I915_TILING_Y) 1197 + val |= 1 << I830_FENCE_TILING_Y_SHIFT; 1198 + val |= I915_FENCE_SIZE_BITS(obj->size); 1199 + val |= pitch_val << I830_FENCE_PITCH_SHIFT; 1200 + val |= I830_FENCE_REG_VALID; 1201 + 1202 + I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); 1203 + } 1204 + 1205 + static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) 1206 + { 1207 + struct drm_gem_object *obj = reg->obj; 1208 + struct drm_device *dev = obj->dev; 1209 + drm_i915_private_t *dev_priv = dev->dev_private; 1210 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 1211 + int regnum = obj_priv->fence_reg; 1212 + uint32_t val; 1213 + uint32_t pitch_val; 1214 + 1215 + if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || 1216 + (obj_priv->gtt_offset & (obj->size - 1))) { 1217 + WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__); 1218 + return; 1219 + } 1220 + 1221 + pitch_val = (obj_priv->stride / 128) - 1; 1222 + 1223 + val = obj_priv->gtt_offset; 1224 + if (obj_priv->tiling_mode == I915_TILING_Y) 1225 + val |= 1 << I830_FENCE_TILING_Y_SHIFT; 1226 + val |= I830_FENCE_SIZE_BITS(obj->size); 1227 + val |= pitch_val << I830_FENCE_PITCH_SHIFT; 1228 + val |= I830_FENCE_REG_VALID; 1229 + 1230 + I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); 1231 + 1232 + } 1233 + 1234 + /** 1235 + * i915_gem_object_get_fence_reg - set up a fence reg for an object 1236 + * @obj: object to map through a fence reg 1237 + * 1238 + * When mapping objects through the GTT, userspace wants to be able to write 1239 + * to them without having to worry about swizzling if the object is tiled. 1240 + * 1241 + * This function walks the fence regs looking for a free one for @obj, 1242 + * stealing one if it can't find any. 1243 + * 1244 + * It then sets up the reg based on the object's properties: address, pitch 1245 + * and tiling format. 1246 + */ 1247 + static void 1248 + i915_gem_object_get_fence_reg(struct drm_gem_object *obj) 1249 + { 1250 + struct drm_device *dev = obj->dev; 1251 + drm_i915_private_t *dev_priv = dev->dev_private; 1252 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 1253 + struct drm_i915_fence_reg *reg = NULL; 1254 + int i, ret; 1255 + 1256 + switch (obj_priv->tiling_mode) { 1257 + case I915_TILING_NONE: 1258 + WARN(1, "allocating a fence for non-tiled object?\n"); 1259 + break; 1260 + case I915_TILING_X: 1261 + WARN(obj_priv->stride & (512 - 1), 1262 + "object is X tiled but has non-512B pitch\n"); 1263 + break; 1264 + case I915_TILING_Y: 1265 + WARN(obj_priv->stride & (128 - 1), 1266 + "object is Y tiled but has non-128B pitch\n"); 1267 + break; 1268 + } 1269 + 1270 + /* First try to find a free reg */ 1271 + for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { 1272 + reg = &dev_priv->fence_regs[i]; 1273 + if (!reg->obj) 1274 + break; 1275 + } 1276 + 1277 + /* None available, try to steal one or wait for a user to finish */ 1278 + if (i == dev_priv->num_fence_regs) { 1279 + struct drm_i915_gem_object *old_obj_priv = NULL; 1280 + loff_t offset; 1281 + 1282 + try_again: 1283 + /* Could try to use LRU here instead... */ 1284 + for (i = dev_priv->fence_reg_start; 1285 + i < dev_priv->num_fence_regs; i++) { 1286 + reg = &dev_priv->fence_regs[i]; 1287 + old_obj_priv = reg->obj->driver_private; 1288 + if (!old_obj_priv->pin_count) 1289 + break; 1290 + } 1291 + 1292 + /* 1293 + * Now things get ugly... we have to wait for one of the 1294 + * objects to finish before trying again. 1295 + */ 1296 + if (i == dev_priv->num_fence_regs) { 1297 + ret = i915_gem_object_wait_rendering(reg->obj); 1298 + if (ret) { 1299 + WARN(ret, "wait_rendering failed: %d\n", ret); 1300 + return; 1301 + } 1302 + goto try_again; 1303 + } 1304 + 1305 + /* 1306 + * Zap this virtual mapping so we can set up a fence again 1307 + * for this object next time we need it. 1308 + */ 1309 + offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; 1310 + unmap_mapping_range(dev->dev_mapping, offset, 1311 + reg->obj->size, 1); 1312 + old_obj_priv->fence_reg = I915_FENCE_REG_NONE; 1313 + } 1314 + 1315 + obj_priv->fence_reg = i; 1316 + reg->obj = obj; 1317 + 1318 + if (IS_I965G(dev)) 1319 + i965_write_fence_reg(reg); 1320 + else if (IS_I9XX(dev)) 1321 + i915_write_fence_reg(reg); 1322 + else 1323 + i830_write_fence_reg(reg); 1324 + } 1325 + 1326 + /** 1327 + * i915_gem_clear_fence_reg - clear out fence register info 1328 + * @obj: object to clear 1329 + * 1330 + * Zeroes out the fence register itself and clears out the associated 1331 + * data structures in dev_priv and obj_priv. 1332 + */ 1333 + static void 1334 + i915_gem_clear_fence_reg(struct drm_gem_object *obj) 1335 + { 1336 + struct drm_device *dev = obj->dev; 1337 + struct drm_i915_private *dev_priv = dev->dev_private; 1338 + struct drm_i915_gem_object *obj_priv = obj->driver_private; 1339 + 1340 + if (IS_I965G(dev)) 1341 + I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); 1342 + else 1343 + I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); 1344 + 1345 + dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; 1346 + obj_priv->fence_reg = I915_FENCE_REG_NONE; 1410 1347 } 1411 1348 1412 1349 /** ··· 2808 2351 2809 2352 obj->driver_private = obj_priv; 2810 2353 obj_priv->obj = obj; 2354 + obj_priv->fence_reg = I915_FENCE_REG_NONE; 2811 2355 INIT_LIST_HEAD(&obj_priv->list); 2356 + 2812 2357 return 0; 2813 2358 } 2814 2359 2815 2360 void i915_gem_free_object(struct drm_gem_object *obj) 2816 2361 { 2362 + struct drm_device *dev = obj->dev; 2363 + struct drm_gem_mm *mm = dev->mm_private; 2364 + struct drm_map_list *list; 2365 + struct drm_map *map; 2817 2366 struct drm_i915_gem_object *obj_priv = obj->driver_private; 2818 2367 2819 2368 while (obj_priv->pin_count > 0) 2820 2369 i915_gem_object_unpin(obj); 2821 2370 2822 2371 i915_gem_object_unbind(obj); 2372 + 2373 + list = &obj->map_list; 2374 + drm_ht_remove_item(&mm->offset_hash, &list->hash); 2375 + 2376 + if (list->file_offset_node) { 2377 + drm_mm_put_block(list->file_offset_node); 2378 + list->file_offset_node = NULL; 2379 + } 2380 + 2381 + map = list->map; 2382 + if (map) { 2383 + drm_free(map, sizeof(*map), DRM_MEM_DRIVER); 2384 + list->map = NULL; 2385 + } 2823 2386 2824 2387 drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); 2825 2388 drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); ··· 2909 2432 */ 2910 2433 i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT), 2911 2434 ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)); 2912 - seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU | 2913 - I915_GEM_DOMAIN_GTT)); 2435 + seqno = i915_add_request(dev, ~I915_GEM_DOMAIN_CPU); 2914 2436 2915 2437 if (seqno == 0) { 2916 2438 mutex_unlock(&dev->struct_mutex); ··· 3233 2757 INIT_DELAYED_WORK(&dev_priv->mm.retire_work, 3234 2758 i915_gem_retire_work_handler); 3235 2759 dev_priv->mm.next_gem_seqno = 1; 2760 + 2761 + /* Old X drivers will take 0-2 for front, back, depth buffers */ 2762 + dev_priv->fence_reg_start = 3; 2763 + 2764 + if (IS_I965G(dev)) 2765 + dev_priv->num_fence_regs = 16; 2766 + else 2767 + dev_priv->num_fence_regs = 8; 3236 2768 3237 2769 i915_gem_detect_bit_6_swizzle(dev); 3238 2770 }
+1
drivers/gpu/drm/i915/i915_gem_tiling.c
··· 208 208 } 209 209 } 210 210 obj_priv->tiling_mode = args->tiling_mode; 211 + obj_priv->stride = args->stride; 211 212 212 213 mutex_unlock(&dev->struct_mutex); 213 214
+19 -1
drivers/gpu/drm/i915/i915_reg.h
··· 175 175 #define DISPLAY_PLANE_B (1<<20) 176 176 177 177 /* 178 + * Fence registers 179 + */ 180 + #define FENCE_REG_830_0 0x2000 181 + #define I830_FENCE_START_MASK 0x07f80000 182 + #define I830_FENCE_TILING_Y_SHIFT 12 183 + #define I830_FENCE_SIZE_BITS(size) ((get_order(size >> 19) - 1) << 8) 184 + #define I830_FENCE_PITCH_SHIFT 4 185 + #define I830_FENCE_REG_VALID (1<<0) 186 + 187 + #define I915_FENCE_START_MASK 0x0ff00000 188 + #define I915_FENCE_SIZE_BITS(size) ((get_order(size >> 20) - 1) << 8) 189 + 190 + #define FENCE_REG_965_0 0x03000 191 + #define I965_FENCE_PITCH_SHIFT 2 192 + #define I965_FENCE_TILING_Y_SHIFT 1 193 + #define I965_FENCE_REG_VALID (1<<0) 194 + 195 + /* 178 196 * Instruction and interrupt control regs 179 197 */ 180 - 181 198 #define PRB0_TAIL 0x02030 182 199 #define PRB0_HEAD 0x02034 183 200 #define PRB0_START 0x02038 ··· 261 244 #define CM0_DEPTH_WRITE_DISABLE (1<<1) 262 245 #define CM0_RC_OP_FLUSH_DISABLE (1<<0) 263 246 #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ 247 + 264 248 265 249 /* 266 250 * Framebuffer compression (915+ only)
+14
include/drm/i915_drm.h
··· 160 160 #define DRM_I915_GEM_SET_TILING 0x21 161 161 #define DRM_I915_GEM_GET_TILING 0x22 162 162 #define DRM_I915_GEM_GET_APERTURE 0x23 163 + #define DRM_I915_GEM_MMAP_GTT 0x24 163 164 164 165 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 165 166 #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) ··· 188 187 #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) 189 188 #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) 190 189 #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) 190 + #define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) 191 191 #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) 192 192 #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) 193 193 #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) ··· 382 380 * This is a fixed-size type for 32/64 compatibility. 383 381 */ 384 382 uint64_t addr_ptr; 383 + }; 384 + 385 + struct drm_i915_gem_mmap_gtt { 386 + /** Handle for the object being mapped. */ 387 + uint32_t handle; 388 + uint32_t pad; 389 + /** 390 + * Fake offset to use for subsequent mmap call 391 + * 392 + * This is a fixed-size type for 32/64 compatibility. 393 + */ 394 + uint64_t offset; 385 395 }; 386 396 387 397 struct drm_i915_gem_set_domain {