Re: [Intel-gfx] [PATCH] drm/i915: ingore eDP bpc settings
Am Freitag, den 10.08.2012, 11:10 +0200 schrieb Daniel Vetter: There is a typo in the commit summary: i*gn*ore. This has originally been introduced to not oversubscribe the dp links in commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Author: Zhenyu Wang zhen...@linux.intel.com Date: Tue Jan 12 05:38:31 2010 +0800 drm/i915: fix pixel color depth setting on eDP Since then we've fixed up the dp link bandwidth calculation code for code `for code` should be removed. and should now automatically fall back to 6bpc dithering. So this is unnecessary. Furthermore it seems to break the new MacbookPro with retina display, hence let's just rip this out. Reported-by: Benoit Gschwind gschw...@gnu-log.net Cc: Benoit Gschwind gschw...@gnu-log.net Cc: Francois Rigaut frig...@gmail.com Cc: Greg KH gre...@linuxfoundation.org Cc: sta...@vger.kernel.org Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch -- Testing feedback highgly welcome, and thanks for Benoit for finding out that the bpc computations are busted. -Daniel --- drivers/gpu/drm/i915/intel_display.c | 11 --- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bddb290..ddd4db3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3755,17 +3755,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, continue; } - if (intel_encoder-type == INTEL_OUTPUT_EDP) { - /* Use VBT settings if we have an eDP panel */ - unsigned int edp_bpc = dev_priv-edp.bpp / 3; - - if (edp_bpc display_bpc) { - DRM_DEBUG_KMS(clamping display bpc (was %d) to eDP (%d)\n, display_bpc, edp_bpc); - display_bpc = edp_bpc; - } - continue; - } - /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, dev-mode_config.connector_list, head) { Acked-by: Paul Menzel paulepan...@users.sourceforge.net Thanks, Paul signature.asc Description: This is a digitally signed message part ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] Netiquette: No HTML messages please. (was: [ANNOUNCE] glamor 0.5.0)
Dear Zhigang, thank you for the announcement message and congratulations on the release. But please do not send HTML messages to lists [1]! Thanks, Paul [1] http://en.opensuse.org/openSUSE:Mailing_list_netiquette signature.asc Description: This is a digitally signed message part ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] Macbook Air 2012
Hi, I installed on my shiny new Macbook Air 2012 Fedora 17. After adding intremap=off to the kernel arguments, I was able to install the system. The X server worked out of the box. This was with a 3.3.4 kernel. Then I started to upgrade the installation and a newer kernel was installed 3.5. After the reboot the screen stayed black. Upgrading to Linus' 3.6-rc1 didn't help either. After some research I have tried now Daniel's tree danvet branch drm-intel-next. Still no success. I also found https://bugs.freedesktop.org/show_bug.cgi?id=48652 which sounds awfully like what I am seeing as symptoms. Unfortunately, is my graphic trouble debugging skills rather limited. Is there anything I could provide to resolve this issue? cheers, daniel ps: Adding nomodeset to the drm-intel-next kernel resulted in a kernel panic: http://www.monom.org/misc/mba/drm-intel-next_nomodeset-2012-08-11.jpg Don't know if that is important. Just in case someone is interested in these kind of reports. ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] Stolen pages, with a little surprise
I've reworked and incorporated dmabuf into the grand scheme of things, unifying how we track pages for the various different types of object (shmemfs, dmabuf, stolen) so the series is quite a bit more complicated than it was before. Please review, flame and generally suggest cleaner methods. -Chris ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 06/29] drm/i915: Protect private gem objects from truncate (such as imported dmabuf)
If the object has no backing shmemfs filp, then we obviously cannot perform a truncation operation upon it. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c |7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b16b5ff..2f4a113 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1385,6 +1385,11 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) { struct inode *inode; + i915_gem_object_free_mmap_offset(obj); + + if (obj-base.filp == NULL) + return; + /* Our goal here is to return as much of the memory as * is possible back to the system as we are called from OOM. * To do this we must instruct the shmfs to drop all of its @@ -1393,8 +1398,6 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) inode = obj-base.filp-f_path.dentry-d_inode; shmem_truncate_range(inode, 0, (loff_t)-1); - i915_gem_object_free_mmap_offset(obj); - obj-madv = __I915_MADV_PURGED; } -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 13/29] drm/i915: Convert the dmabuf object to use the new i915_gem_object_ops
By providing a callback for when we need to bind the pages, and then release them again later, we can shorten the amount of time we hold the foreign pages mapped and pinned, and importantly the dmabuf objects then behave as any other normal object with respect to the shrinker and memory management. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h|1 - drivers/gpu/drm/i915/i915_gem.c| 10 +++ drivers/gpu/drm/i915/i915_gem_dmabuf.c | 45 +--- drivers/gpu/drm/i915/i915_gem_gtt.c|4 +-- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d4d3b2a..74a3c6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -993,7 +993,6 @@ struct drm_i915_gem_object { int pages_pin_count; /* prime dma-buf support */ - struct sg_table *sg_table; void *dma_buf_vmapping; int vmapping_count; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 20e05c2..d0fcb61 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1450,7 +1450,7 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { const struct drm_i915_gem_object_ops *ops = obj-base.driver_private; - if (obj-sg_table || obj-pages == NULL) + if (obj-pages == NULL) return 0; if (obj-pages_pin_count) @@ -1594,7 +1594,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) const struct drm_i915_gem_object_ops *ops = obj-base.driver_private; int ret; - if (obj-sg_table || obj-pages) + if (obj-pages) return 0; BUG_ON(obj-pages_pin_count); @@ -3680,9 +3680,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) trace_i915_gem_object_destroy(obj); - if (gem_obj-import_attach) - drm_prime_gem_destroy(gem_obj, obj-sg_table); - if (obj-phys_obj) i915_gem_detach_phys_object(dev, obj); @@ -3704,6 +3701,9 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) BUG_ON(obj-pages); + if (obj-base.import_attach) + drm_prime_gem_destroy(obj-base, NULL); + drm_gem_object_release(obj-base); i915_gem_info_remove_obj(dev_priv, obj-base.size); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index b48c2a4..5e72e95 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -82,7 +82,8 @@ out: } static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *sg, enum dma_data_direction dir) + struct sg_table *sg, + enum dma_data_direction dir) { dma_unmap_sg(attachment-dev, sg-sgl, sg-nents, dir); sg_free_table(sg); @@ -212,11 +213,35 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return dma_buf_export(obj, i915_dmabuf_ops, obj-base.size, 0600); } +static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +{ + struct sg_table *sg; + + sg = dma_buf_map_attachment(obj-base.import_attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sg)) + return PTR_ERR(sg); + + obj-pages = sg; + obj-has_dma_mapping = true; + return 0; +} + +static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj) +{ + dma_buf_unmap_attachment(obj-base.import_attach, +obj-pages, DMA_BIDIRECTIONAL); + obj-has_dma_mapping = false; +} + +static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = { + .get_pages = i915_gem_object_get_pages_dmabuf, + .put_pages = i915_gem_object_put_pages_dmabuf, +}; + struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf) { struct dma_buf_attachment *attach; - struct sg_table *sg; struct drm_i915_gem_object *obj; int ret; @@ -235,32 +260,24 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, if (IS_ERR(attach)) return ERR_CAST(attach); - sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); - if (IS_ERR(sg)) { - ret = PTR_ERR(sg); - goto fail_detach; - } obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (obj == NULL) { ret = -ENOMEM; - goto fail_unmap; + goto fail_detach; } ret = drm_gem_private_object_init(dev, obj-base, dma_buf-size); if (ret) { kfree(obj); - goto fail_unmap; + goto fail_detach; } -
[Intel-gfx] [PATCH 15/29] drm/i915: Fix detection of stolen base for gen2
It was not until the G33 refresh, that a PCI config register was introduced that explicitly said where the stolen memory was. Prior to 865G there was not even a register that said where the end of usable low memory was and where the stolen memory began (or ended depending upon chipset). Before then, one has to look at the BIOS memory maps to find the Top of Memory. Alas that is not exported by arch/x86 and so we have to resort to disabling stolen memory on gen2 for the time being. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h|1 + drivers/gpu/drm/i915/i915_gem_stolen.c | 69 ++-- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 74a3c6c..a25edcc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -704,6 +704,7 @@ typedef struct drm_i915_private { unsigned long gtt_start; unsigned long gtt_mappable_end; unsigned long gtt_end; + unsigned long stolen_base; /* limited to low memory (32-bit) */ struct io_mapping *gtt_mapping; phys_addr_t gtt_base_addr; diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index ada2e90..a01ff74 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -43,56 +43,43 @@ * for is a boon. */ -#define PTE_ADDRESS_MASK 0xf000 -#define PTE_ADDRESS_MASK_HIGH 0x00f0 /* i915+ */ -#define PTE_MAPPING_TYPE_UNCACHED (0 1) -#define PTE_MAPPING_TYPE_DCACHE(1 1) /* i830 only */ -#define PTE_MAPPING_TYPE_CACHED(3 1) -#define PTE_MAPPING_TYPE_MASK (3 1) -#define PTE_VALID (1 0) - -/** - * i915_stolen_to_phys - take an offset into stolen memory and turn it into - * a physical one - * @dev: drm device - * @offset: address to translate - * - * Some chip functions require allocations from stolen space and need the - * physical address of the memory in question. - */ -static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset) +static unsigned long i915_stolen_to_physical(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev-dev_private; struct pci_dev *pdev = dev_priv-bridge_dev; u32 base; -#if 0 /* On the machines I have tested the Graphics Base of Stolen Memory -* is unreliable, so compute the base by subtracting the stolen memory -* from the Top of Low Usable DRAM which is where the BIOS places -* the graphics stolen memory. +* is unreliable, so on those compute the base by subtracting the +* stolen memory from the Top of Low Usable DRAM which is where the +* BIOS places the graphics stolen memory. +* +* On gen2, the layout is slightly different with the Graphics Segment +* immediately following Top of Memory (or Top of Usable DRAM). Note +* it appears that TOUD is only reported by 865g, so we just use the +* top of memory as determined by the e820 probe. +* +* XXX gen2 requires an unavailable symbol and 945gm fails with +* its value of TOLUD. */ + base = 0; if (INTEL_INFO(dev)-gen 3 || IS_G33(dev)) { - /* top 32bits are reserved = 0 */ + /* Read Graphics Base of Stolen Memory directly */ pci_read_config_dword(pdev, 0xA4, base); - } else { - /* XXX presume 8xx is the same as i915 */ - pci_bus_read_config_dword(pdev-bus, 2, 0x5C, base); - } -#else - if (INTEL_INFO(dev)-gen 3 || IS_G33(dev)) { - u16 val; - pci_read_config_word(pdev, 0xb0, val); - base = val 4 20; - } else { +#if 0 + } else if (IS_GEN3(dev)) { u8 val; + /* Stolen is immediately below Top of Low Usable DRAM */ pci_read_config_byte(pdev, 0x9c, val); base = val 3 27; - } - base -= dev_priv-mm.gtt-stolen_size; + base -= dev_priv-mm.gtt-stolen_size; + } else { + /* Stolen is immediately above Top of Memory */ + base = max_low_pfn_mapped PAGE_SHIFT; #endif + } - return base + offset; + return base; } static void i915_warn_stolen(struct drm_device *dev) @@ -117,7 +104,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) if (!compressed_fb) goto err; - cfb_base = i915_stolen_to_phys(dev, compressed_fb-start); + cfb_base = dev_priv-mm.stolen_base + compressed_fb-start; if (!cfb_base) goto err_fb; @@ -130,7 +117,7 @@ static void i915_setup_compression(struct
[Intel-gfx] [PATCH 17/29] drm/i915: Avoid clearing preallocated regions from the GTT
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h |2 ++ drivers/gpu/drm/i915/i915_gem_gtt.c | 35 --- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a25edcc..0ce410a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -896,6 +896,8 @@ enum i915_cache_level { I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */ }; +#define I915_GTT_RESERVED ((struct drm_mm_node *)0x1) + struct drm_i915_gem_object_ops { int (*get_pages)(struct drm_i915_gem_object *); void (*put_pages)(struct drm_i915_gem_object *); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ea4fc20..528fd43 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -375,18 +375,47 @@ void i915_gem_init_global_gtt(struct drm_device *dev, unsigned long end) { drm_i915_private_t *dev_priv = dev-dev_private; + struct drm_mm_node *entry; + struct drm_i915_gem_object *obj; - /* Substract the guard page ... */ + /* Subtract the guard page ... */ drm_mm_init(dev_priv-mm.gtt_space, start, end - start - PAGE_SIZE); if (!HAS_LLC(dev)) dev_priv-mm.gtt_space.color_adjust = i915_gtt_color_adjust; + /* Mark any preallocated objects as occupied */ + list_for_each_entry(obj, dev_priv-mm.bound_list, gtt_list) { + DRM_DEBUG_KMS(reserving preallocated space: %x + %zx\n, + obj-gtt_offset, obj-base.size); + + BUG_ON(obj-gtt_space != I915_GTT_RESERVED); + obj-gtt_space = drm_mm_create_block(dev_priv-mm.gtt_space, +obj-gtt_offset, +obj-base.size, +false); + obj-has_global_gtt_mapping = 1; + } + dev_priv-mm.gtt_start = start; dev_priv-mm.gtt_mappable_end = mappable_end; dev_priv-mm.gtt_end = end; dev_priv-mm.gtt_total = end - start; dev_priv-mm.mappable_gtt_total = min(end, mappable_end) - start; - /* ... but ensure that we clear the entire range. */ - intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE); + /* Clear any non-preallocated blocks */ + list_for_each_entry(entry, dev_priv-mm.gtt_space.hole_stack, hole_stack) { + unsigned long hole_start = entry-start + entry-size; + unsigned long hole_end = list_entry(entry-node_list.next, + struct drm_mm_node, + node_list)-start; + + DRM_DEBUG_KMS(clearing unused GTT space: [%lx, %lx]\n, + hole_start, hole_end); + + intel_gtt_clear_range(hole_start / PAGE_SIZE, + (hole_end-hole_start) / PAGE_SIZE); + } + + /* And finally clear the reserved guard page */ + intel_gtt_clear_range(end / PAGE_SIZE - 1, 1); } -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 22/29] drm/i915: Handle stolen objects in pwrite
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 169 +-- 1 file changed, 111 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 552f95b..a2fb2aa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -664,19 +664,17 @@ out: * needs_clflush_before is set and flushes out any written cachelines after * writing if needs_clflush is set. */ static int -shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, +shmem_pwrite_fast(char *vaddr, int shmem_page_offset, int page_length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush_before, bool needs_clflush_after) { - char *vaddr; int ret; if (unlikely(page_do_bit17_swizzling)) return -EINVAL; - vaddr = kmap_atomic(page); if (needs_clflush_before) drm_clflush_virt_range(vaddr + shmem_page_offset, page_length); @@ -686,7 +684,6 @@ shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, if (needs_clflush_after) drm_clflush_virt_range(vaddr + shmem_page_offset, page_length); - kunmap_atomic(vaddr); return ret ? -EFAULT : 0; } @@ -694,16 +691,14 @@ shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, /* Only difference to the fast-path function is that this can handle bit17 * and uses non-atomic copy and kmap functions. */ static int -shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, +shmem_pwrite_slow(char *vaddr, int shmem_page_offset, int page_length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush_before, bool needs_clflush_after) { - char *vaddr; int ret; - vaddr = kmap(page); if (unlikely(needs_clflush_before || page_do_bit17_swizzling)) shmem_clflush_swizzled_range(vaddr + shmem_page_offset, page_length, @@ -720,7 +715,6 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, shmem_clflush_swizzled_range(vaddr + shmem_page_offset, page_length, page_do_bit17_swizzling); - kunmap(page); return ret ? -EFAULT : 0; } @@ -731,6 +725,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_i915_gem_pwrite *args, struct drm_file *file) { + struct drm_i915_private *dev_priv = dev-dev_private; ssize_t remain; loff_t offset; char __user *user_data; @@ -770,74 +765,132 @@ i915_gem_shmem_pwrite(struct drm_device *dev, if (ret) return ret; - i915_gem_object_pin_pages(obj); - offset = args-offset; obj-dirty = 1; - for_each_sg(obj-pages-sgl, sg, obj-pages-nents, i) { - struct page *page; - int partial_cacheline_write; + if (obj-stolen) { + while (remain 0) { + char *vaddr; + int partial_cacheline_write; - if (i offset PAGE_SHIFT) - continue; + /* Operation in this page +* +* shmem_page_offset = offset within page in shmem file +* page_length = bytes to copy for this page +*/ + shmem_page_offset = offset_in_page(offset); - if (remain = 0) - break; + page_length = remain; + if ((shmem_page_offset + page_length) PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; - /* Operation in this page -* -* shmem_page_offset = offset within page in shmem file -* page_length = bytes to copy for this page -*/ - shmem_page_offset = offset_in_page(offset); + /* If we don't overwrite a cacheline completely we need to be +* careful to have up-to-date data by first clflushing. Don't +* overcomplicate things and flush the entire patch. */ + partial_cacheline_write = needs_clflush_before + ((shmem_page_offset | page_length) + (boot_cpu_data.x86_clflush_size - 1)); - page_length = remain; - if ((shmem_page_offset +
[Intel-gfx] [PATCH 27/29] drm/i915: Allocate overlay registers from stolen memory
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_overlay.c |6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 7a98459..6982191 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1424,8 +1424,10 @@ void intel_setup_overlay(struct drm_device *dev) overlay-dev = dev; - reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); - if (!reg_bo) + reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE); + if (reg_bo == NULL) + reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); + if (reg_bo == NULL) goto out_free; overlay-reg_bo = reg_bo; -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 29/29] drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl
By exporting the ability to map user address and inserting PTEs representing their backing pages into the GTT, we can exploit UMA in order to utilize normal application data as a texture source or even as a render target (depending upon the capabilities of the chipset). This has a number of uses, with zero-copy downloads to the GPU and efficient readback making the intermixed streaming of CPU and GPU operations fairly efficient. This ability has many widespread implications from faster rendering of partial software fallbacks (xterm!) to faster pipelining of texture data (such as pixel buffer objects in GL). Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile |1 + drivers/gpu/drm/i915/i915_dma.c |1 + drivers/gpu/drm/i915/i915_drv.h | 14 +++ drivers/gpu/drm/i915/i915_gem.c |6 +- drivers/gpu/drm/i915/i915_gem_userptr.c | 209 +++ include/drm/i915_drm.h | 15 +++ 6 files changed, 243 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_userptr.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0f2c549..754d665 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -14,6 +14,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915_gem_gtt.o \ i915_gem_stolen.o \ i915_gem_tiling.o \ + i915_gem_userptr.o \ i915_sysfs.o \ i915_trace_points.o \ intel_display.o \ diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 07f5b2e..62928fc 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1884,6 +1884,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_MASTER|DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f0bf78f..50c635f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1045,6 +1045,18 @@ struct drm_i915_gem_object { atomic_t pending_flip; }; +struct i915_gem_userptr_object { + struct drm_i915_gem_object gem; + uintptr_t user_ptr; + size_t user_size; + int read_only; +}; + +union drm_i915_gem_objects { + struct drm_i915_gem_object base; + struct i915_gem_userptr_object userptr; +}; + inline static bool i915_gem_object_is_prime(struct drm_i915_gem_object *obj) { return obj-base.import_attach != NULL; @@ -1303,6 +1315,8 @@ int i915_gem_entervt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_userptr_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); int i915_gem_set_tiling(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_tiling(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2d7adbb..1c8904a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2517,9 +2517,9 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) /* Avoid an unnecessary call to unbind on rebind. */ obj-map_and_fenceable = true; + obj-gtt_offset -= obj-gtt_space-start; drm_mm_put_block(obj-gtt_space); obj-gtt_space = NULL; - obj-gtt_offset = 0; return 0; } @@ -3035,7 +3035,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, list_move_tail(obj-gtt_list, dev_priv-mm.bound_list); list_add_tail(obj-mm_list, dev_priv-mm.inactive_list); - obj-gtt_offset = obj-gtt_space-start; + obj-gtt_offset += obj-gtt_space-start; fenceable = obj-gtt_space-size == fence_size @@ -4214,7 +4214,7 @@ i915_gem_load(struct drm_device *dev) dev_priv-slab = kmem_cache_create(i915_gem_object, - sizeof(struct drm_i915_gem_object), 0, + sizeof(union drm_i915_gem_objects), 0, SLAB_HWCACHE_ALIGN, NULL); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c new file mode 100644 index 000..8604dad --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -0,0 +1,209 @@ +/* + * Copyright
[Intel-gfx] [PATCH 25/29] drm/i915: Allocate fbcon from stolen memory
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_fb.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 97f6735..9de9cd9 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -84,7 +84,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, size = mode_cmd.pitches[0] * mode_cmd.height; size = ALIGN(size, PAGE_SIZE); - obj = i915_gem_alloc_object(dev, size); + obj = i915_gem_object_create_stolen(dev, size); + if (obj == NULL) + obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR(failed to allocate framebuffer\n); ret = -ENOMEM; -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 23/29] drm/i915: Handle stolen objects for pread
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 175 ++- 1 file changed, 116 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a2fb2aa..a29c259 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -324,24 +324,21 @@ __copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset, * Flushes invalid cachelines before reading the target if * needs_clflush is set. */ static int -shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length, +shmem_pread_fast(char *vaddr, int shmem_page_offset, int page_length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush) { - char *vaddr; int ret; if (unlikely(page_do_bit17_swizzling)) return -EINVAL; - vaddr = kmap_atomic(page); if (needs_clflush) drm_clflush_virt_range(vaddr + shmem_page_offset, page_length); ret = __copy_to_user_inatomic(user_data, vaddr + shmem_page_offset, page_length); - kunmap_atomic(vaddr); return ret ? -EFAULT : 0; } @@ -371,14 +368,12 @@ shmem_clflush_swizzled_range(char *addr, unsigned long length, /* Only difference to the fast-path function is that this can handle bit17 * and uses non-atomic copy and kmap functions. */ static int -shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, +shmem_pread_slow(char *vaddr, int shmem_page_offset, int page_length, char __user *user_data, bool page_do_bit17_swizzling, bool needs_clflush) { - char *vaddr; int ret; - vaddr = kmap(page); if (needs_clflush) shmem_clflush_swizzled_range(vaddr + shmem_page_offset, page_length, @@ -392,7 +387,6 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, ret = __copy_to_user(user_data, vaddr + shmem_page_offset, page_length); - kunmap(page); return ret ? - EFAULT : 0; } @@ -403,6 +397,7 @@ i915_gem_shmem_pread(struct drm_device *dev, struct drm_i915_gem_pread *args, struct drm_file *file) { + struct drm_i915_private *dev_priv = dev-dev_private; char __user *user_data; ssize_t remain; loff_t offset; @@ -433,76 +428,138 @@ i915_gem_shmem_pread(struct drm_device *dev, } } - ret = i915_gem_object_get_pages(obj); - if (ret) - return ret; + offset = args-offset; - i915_gem_object_pin_pages(obj); + if (obj-stolen) { + char *vaddr; - offset = args-offset; + vaddr = (char *)dev_priv-mm.stolen_base; + vaddr += obj-stolen-start + offset; - for_each_sg(obj-pages-sgl, sg, obj-pages-nents, i) { - struct page *page; + shmem_page_offset = offset_in_page(offset); + while (remain 0) { + /* Operation in this page +* +* shmem_page_offset = offset within page in shmem file +* page_length = bytes to copy for this page +*/ + page_length = remain; + if ((shmem_page_offset + page_length) PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; - if (i offset PAGE_SHIFT) - continue; + page_do_bit17_swizzling = obj_do_bit17_swizzling + ((uintptr_t)vaddr (1 17)) != 0; - if (remain = 0) - break; + ret = shmem_pread_fast(vaddr, shmem_page_offset, page_length, + user_data, page_do_bit17_swizzling, + needs_clflush); + if (ret == 0) + goto next_stolen; - /* Operation in this page -* -* shmem_page_offset = offset within page in shmem file -* page_length = bytes to copy for this page -*/ - shmem_page_offset = offset_in_page(offset); - page_length = remain; - if ((shmem_page_offset + page_length) PAGE_SIZE) - page_length = PAGE_SIZE - shmem_page_offset; + hit_slowpath = 1; + mutex_unlock(dev-struct_mutex); - page = sg_page(sg); -
[Intel-gfx] [PATCH 26/29] drm/i915: Allocate ringbuffers from stolen memory
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_ringbuffer.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5fdd297..7e6f8f4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1016,7 +1016,11 @@ static int intel_init_ring_buffer(struct drm_device *dev, return ret; } - obj = i915_gem_alloc_object(dev, ring-size); + obj = NULL; + if (!HAS_LLC(dev)) + obj = i915_gem_object_create_stolen(dev, ring-size); + if (obj == NULL) + obj = i915_gem_alloc_object(dev, ring-size); if (obj == NULL) { DRM_ERROR(Failed to allocate ringbuffer\n); ret = -ENOMEM; -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 28/29] drm/i915: Use a slab for object allocation
The primary purpose of this was to debug some use-after-free memory corruption that was causing an OOPS inside drm/i915. As it turned out the corruption was being caused elsewhere and i915.ko as a major user of many objects was being hit hardest. Indeed as we do frequent the generic kmalloc caches, dedicating one to ourselves (or at least naming one for us depending upon the core) aids debugging our own slab usage. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_dma.c|3 +++ drivers/gpu/drm/i915/i915_drv.h|4 drivers/gpu/drm/i915/i915_gem.c| 28 +++- drivers/gpu/drm/i915/i915_gem_dmabuf.c |5 ++--- drivers/gpu/drm/i915/i915_gem_stolen.c |4 ++-- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index df6490b..07f5b2e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1759,6 +1759,9 @@ int i915_driver_unload(struct drm_device *dev) destroy_workqueue(dev_priv-wq); + if (dev_priv-slab) + kmem_cache_destroy(dev_priv-slab); + pci_dev_put(dev_priv-bridge_dev); kfree(dev-dev_private); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 03cd1d6..f0bf78f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -390,6 +390,7 @@ struct intel_gmbus { typedef struct drm_i915_private { struct drm_device *dev; + struct kmem_cache *slab; const struct intel_device_info *info; @@ -1311,12 +1312,15 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); +void *i915_gem_object_alloc(struct drm_device *dev); +void i915_gem_object_free(struct drm_i915_gem_object *obj); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops); struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size); void i915_gem_free_object(struct drm_gem_object *obj); + int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, uint32_t alignment, bool map_and_fenceable, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df73e02..2d7adbb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -193,6 +193,18 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, return 0; } +void *i915_gem_object_alloc(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev-dev_private; + return kmem_cache_alloc(dev_priv-slab, GFP_KERNEL | __GFP_ZERO); +} + +void i915_gem_object_free(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = obj-base.dev-dev_private; + kmem_cache_free(dev_priv-slab, obj); +} + static int i915_gem_create(struct drm_file *file, struct drm_device *dev, @@ -216,7 +228,7 @@ i915_gem_create(struct drm_file *file, if (ret) { drm_gem_object_release(obj-base); i915_gem_info_remove_obj(dev-dev_private, obj-base.size); - kfree(obj); + i915_gem_object_free(obj); return ret; } @@ -3731,12 +3743,12 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, struct address_space *mapping; u32 mask; - obj = kzalloc(sizeof(*obj), GFP_KERNEL); + obj = i915_gem_object_alloc(dev); if (obj == NULL) return NULL; if (drm_gem_object_init(dev, obj-base, size) != 0) { - kfree(obj); + i915_gem_object_free(obj); return NULL; } @@ -3819,7 +3831,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) i915_gem_info_remove_obj(dev_priv, obj-base.size); kfree(obj-bit_17); - kfree(obj); + i915_gem_object_free(obj); } int @@ -4197,8 +4209,14 @@ init_ring_lists(struct intel_ring_buffer *ring) void i915_gem_load(struct drm_device *dev) { - int i; drm_i915_private_t *dev_priv = dev-dev_private; + int i; + + dev_priv-slab = + kmem_cache_create(i915_gem_object, + sizeof(struct drm_i915_gem_object), 0, + SLAB_HWCACHE_ALIGN, + NULL); INIT_LIST_HEAD(dev_priv-mm.active_list); INIT_LIST_HEAD(dev_priv-mm.inactive_list); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
[Intel-gfx] [PATCH 21/29] drm/i915: Support readback of stolen objects upon error
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c |8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2ec8ad7..f59eace 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -895,6 +895,14 @@ i915_error_object_create(struct drm_i915_private *dev_priv, reloc_offset); memcpy_fromio(d, s, PAGE_SIZE); io_mapping_unmap_atomic(s); + } else if (src-stolen) { + unsigned long offset; + + offset = dev_priv-mm.stolen_base; + offset += src-stolen-start; + offset += i PAGE_SHIFT; + + memcpy_fromio(d, (void *)offset, PAGE_SIZE); } else { struct page *page; void *s; -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 20/29] drm/i915: Differentiate between prime and stolen objects
Stolen objects also share the property that they have no backing shmemfs filp, but they can be used with pwrite/pread/gtt-mapping. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h |5 + drivers/gpu/drm/i915/i915_gem.c |4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d6cf758..02de587 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1044,6 +1044,11 @@ struct drm_i915_gem_object { atomic_t pending_flip; }; +inline static bool i915_gem_object_is_prime(struct drm_i915_gem_object *obj) +{ + return obj-base.import_attach != NULL; +} + #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d0fcb61..552f95b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -553,7 +553,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, /* prime objects have no backing filp to GEM pread/pwrite * pages from. */ - if (!obj-base.filp) { + if (i915_gem_object_is_prime(obj)) { ret = -EINVAL; goto out; } @@ -902,7 +902,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, /* prime objects have no backing filp to GEM pread/pwrite * pages from. */ - if (!obj-base.filp) { + if (i915_gem_object_is_prime(obj)) { ret = -EINVAL; goto out; } -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 24/29] drm/i915: Introduce i915_gem_object_create_stolen()
Allow for the creation of GEM objects backed by stolen memory. As these are not backed by ordinary pages, we create a fake dma mapping and store the address in the scatterlist rather than obj-pages. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h|3 + drivers/gpu/drm/i915/i915_gem.c|1 + drivers/gpu/drm/i915/i915_gem_stolen.c | 122 3 files changed, 126 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 02de587..03cd1d6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1495,6 +1495,9 @@ int i915_gem_evict_everything(struct drm_device *dev); int i915_gem_init_stolen(struct drm_device *dev); int i915_gem_stolen_setup_compression(struct drm_device *dev); void i915_gem_cleanup_stolen(struct drm_device *dev); +struct drm_i915_gem_object * +i915_gem_object_create_stolen(struct drm_device *dev, u32 size); +void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj); /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a29c259..df73e02 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3808,6 +3808,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) obj-pages_pin_count = 0; i915_gem_object_put_pages(obj); i915_gem_object_free_mmap_offset(obj); + i915_gem_object_release_stolen(obj); BUG_ON(obj-pages); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 00b1c1d..eca3af1 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -202,3 +202,125 @@ int i915_gem_init_stolen(struct drm_device *dev) return 0; } + +static struct sg_table * +i915_pages_create_for_stolen(struct drm_device *dev, +u32 offset, u32 size) +{ + struct drm_i915_private *dev_priv = dev-dev_private; + struct sg_table *st; + struct scatterlist *sg; + + /* We hide that we have no struct page backing our stolen object +* by wrapping the contiguous physical allocation with a fake +* dma mapping in a single scatterlist. +*/ + + st = kmalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) + return NULL; + + if (!sg_alloc_table(st, 1, GFP_KERNEL)) { + kfree(st); + return NULL; + } + + sg = st-sgl; + sg-offset = offset; + sg-length = size; + + sg_dma_address(sg) = dev_priv-mm.stolen_base + offset; + sg_dma_len(sg) = size; + + return st; +} + +static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) +{ + BUG(); + return -EINVAL; +} + +static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj) +{ + /* Should only be called during free */ + sg_free_table(obj-pages); + kfree(obj-pages); +} + +static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = { + .get_pages = i915_gem_object_get_pages_stolen, + .put_pages = i915_gem_object_put_pages_stolen, +}; + +struct drm_i915_gem_object * +_i915_gem_object_create_stolen(struct drm_device *dev, + struct drm_mm_node *stolen) +{ + struct drm_i915_gem_object *obj; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (obj == NULL) + return NULL; + + if (drm_gem_private_object_init(dev, obj-base, stolen-size)) + goto cleanup; + + i915_gem_object_init(obj, i915_gem_object_stolen_ops); + + obj-pages = i915_pages_create_for_stolen(dev, + stolen-start, stolen-size); + if (obj-pages == NULL) + goto cleanup; + + obj-has_dma_mapping = true; + obj-pages_pin_count = 1; + obj-stolen = stolen; + + obj-base.write_domain = I915_GEM_DOMAIN_GTT; + obj-base.read_domains = I915_GEM_DOMAIN_GTT; + obj-cache_level = I915_CACHE_NONE; + + return obj; + +cleanup: + kfree(obj); + return NULL; +} + +struct drm_i915_gem_object * +i915_gem_object_create_stolen(struct drm_device *dev, u32 size) +{ + struct drm_i915_private *dev_priv = dev-dev_private; + struct drm_i915_gem_object *obj; + struct drm_mm_node *stolen; + + if (dev_priv-mm.stolen_base == 0) + return 0; + + DRM_DEBUG_KMS(creating stolen object: size=%x\n, size); + if (size == 0) + return NULL; + + stolen = drm_mm_search_free(dev_priv-mm.stolen, size, 4096, 0); + if (stolen) + stolen = drm_mm_get_block(stolen, size, 4096); + if (stolen == NULL) + return NULL; + + obj = _i915_gem_object_create_stolen(dev,
[Intel-gfx] [PATCH 18/29] drm/i915: Delay allocation of stolen space for FBC
As we may wish to wrap regions preallocated by the BIOS, we need to do that before carving out contiguous chunks of stolen space for FBC. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h|1 + drivers/gpu/drm/i915/i915_gem_stolen.c | 114 +--- drivers/gpu/drm/i915/intel_display.c |3 + drivers/gpu/drm/i915/intel_pm.c| 13 ++-- 4 files changed, 70 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0ce410a..0fec169 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1486,6 +1486,7 @@ int i915_gem_evict_everything(struct drm_device *dev); /* i915_gem_stolen.c */ int i915_gem_init_stolen(struct drm_device *dev); +int i915_gem_stolen_setup_compression(struct drm_device *dev); void i915_gem_cleanup_stolen(struct drm_device *dev); /* i915_gem_tiling.c */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index a528e4a..00b1c1d 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -86,21 +86,13 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) return base; } -static void i915_warn_stolen(struct drm_device *dev) -{ - DRM_INFO(not enough stolen space for compressed buffer, disabling\n); - DRM_INFO(hint: you may be able to increase stolen memory size in the BIOS to avoid this\n); -} - -static void i915_setup_compression(struct drm_device *dev, int size) +static int i915_setup_compression(struct drm_device *dev, int size) { struct drm_i915_private *dev_priv = dev-dev_private; struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb); - unsigned long cfb_base; - unsigned long ll_base = 0; - /* Just in case the BIOS is doing something questionable. */ - intel_disable_fbc(dev); + DRM_DEBUG_KMS(reserving %d bytes of contiguous stolen space for FBC\n, + size); compressed_fb = drm_mm_search_free(dev_priv-mm.stolen, size, 4096, 0); if (compressed_fb) @@ -108,11 +100,11 @@ static void i915_setup_compression(struct drm_device *dev, int size) if (!compressed_fb) goto err; - cfb_base = dev_priv-mm.stolen_base + compressed_fb-start; - if (!cfb_base) - goto err_fb; - - if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) { + if (HAS_PCH_SPLIT(dev)) + I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb-start); + else if (IS_GM45(dev)) { + I915_WRITE(DPFC_CB_BASE, compressed_fb-start); + } else { compressed_llb = drm_mm_search_free(dev_priv-mm.stolen, 4096, 4096, 0); if (compressed_llb) @@ -121,56 +113,82 @@ static void i915_setup_compression(struct drm_device *dev, int size) if (!compressed_llb) goto err_fb; - ll_base = dev_priv-mm.stolen_base + compressed_llb-start; - if (!ll_base) - goto err_llb; - } + dev_priv-compressed_llb = compressed_llb; - dev_priv-cfb_size = size; + I915_WRITE(FBC_CFB_BASE, + dev_priv-mm.stolen_base + compressed_fb-start); + I915_WRITE(FBC_LL_BASE, + dev_priv-mm.stolen_base + compressed_llb-start); + } dev_priv-compressed_fb = compressed_fb; - if (HAS_PCH_SPLIT(dev)) - I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb-start); - else if (IS_GM45(dev)) { - I915_WRITE(DPFC_CB_BASE, compressed_fb-start); - } else { - I915_WRITE(FBC_CFB_BASE, cfb_base); - I915_WRITE(FBC_LL_BASE, ll_base); - dev_priv-compressed_llb = compressed_llb; - } + dev_priv-cfb_size = size; - DRM_DEBUG_KMS(FBC base 0x%08lx, ll base 0x%08lx, size %dM\n, - (long)cfb_base, (long)ll_base, size 20); - return; + return size; -err_llb: - drm_mm_put_block(compressed_llb); err_fb: drm_mm_put_block(compressed_fb); err: dev_priv-no_fbc_reason = FBC_STOLEN_TOO_SMALL; - i915_warn_stolen(dev); + DRM_INFO(not enough stolen space for compressed buffer (need %d bytes), disabling\n, size); + DRM_INFO(hint: you may be able to increase stolen memory size in the BIOS to avoid this\n); + return 0; +} + +int i915_gem_stolen_setup_compression(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev-dev_private; + struct drm_mm_node *entry; + unsigned long size; + + if (dev_priv-mm.stolen_base == 0) + return 0; + + if (dev_priv-cfb_size) + return dev_priv-cfb_size; + + /* Try to set up FBC with
[Intel-gfx] [PATCH 16/29] drm/i915: Fix location of stolen memory register for SandyBridge+
A few of the earlier registers where enlarged and so the Base Data of Stolem Memory Register (BDSM) was pushed to 0xb0. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_stolen.c |9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index a01ff74..a528e4a 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -63,7 +63,11 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * its value of TOLUD. */ base = 0; - if (INTEL_INFO(dev)-gen 3 || IS_G33(dev)) { + if (INTEL_INFO(dev)-gen = 6) { + /* Read Base Data of Stolen Memory Register (BDSM) directly */ + pci_read_config_dword(pdev, 0xB0, base); + base = ~4095; /* lower bits used for locking register */ + } else if (INTEL_INFO(dev)-gen 3 || IS_G33(dev)) { /* Read Graphics Base of Stolen Memory directly */ pci_read_config_dword(pdev, 0xA4, base); #if 0 @@ -172,6 +176,9 @@ int i915_gem_init_stolen(struct drm_device *dev) if (dev_priv-mm.stolen_base == 0) return 0; + DRM_DEBUG_KMS(found %d bytes of stolen memory at %08lx\n, + dev_priv-mm.gtt-stolen_size, dev_priv-mm.stolen_base); + /* Basic memrange allocator for stolen space */ drm_mm_init(dev_priv-mm.stolen, 0, prealloc_size); -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 14/29] drm: Introduce drm_mm_create_block()
To be used later by i915 to preallocate exact blocks of space from the range manager. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk Cc: Dave Airlie airl...@redhat.com --- drivers/gpu/drm/drm_mm.c | 49 ++ include/drm/drm_mm.h |4 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 9bb82f7..5db8c20 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -161,6 +161,55 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, } } +struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, + unsigned long start, + unsigned long size, + bool atomic) +{ + struct drm_mm_node *hole, *node; + unsigned long end = start + size; + + list_for_each_entry(hole, mm-hole_stack, hole_stack) { + unsigned long hole_start; + unsigned long hole_end; + + BUG_ON(!hole-hole_follows); + hole_start = drm_mm_hole_node_start(hole); + hole_end = drm_mm_hole_node_end(hole); + + if (hole_start start || hole_end end) + continue; + + node = drm_mm_kmalloc(mm, atomic); + if (unlikely(node == NULL)) + return NULL; + + node-start = start; + node-size = size; + node-mm = mm; + node-allocated = 1; + + INIT_LIST_HEAD(node-hole_stack); + list_add(node-node_list, hole-node_list); + + if (start == hole_start) { + hole-hole_follows = 0; + list_del_init(hole-hole_stack); + } + + node-hole_follows = 0; + if (end != hole_end) { + list_add(node-hole_stack, mm-hole_stack); + node-hole_follows = 1; + } + + return node; + } + + return NULL; +} +EXPORT_SYMBOL(drm_mm_create_block); + struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, unsigned long size, unsigned alignment, diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 06d7f79..4020f96 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -102,6 +102,10 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) /* * Basic range manager support (drm_mm.c) */ +extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, + unsigned long start, + unsigned long size, + bool atomic); extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, unsigned long size, unsigned alignment, -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 19/29] drm/i915: Allow objects to be created with no backing pages, but stolen space
In order to accommodate objects that are not backed by struct pages, but instead point into a contiguous region of stolen space, we need to make various changes to avoid dereferencing obj-pages or obj-base.filp. First introduce a marker for the stolen object, that specifies its offset into the stolen region and implies that it has no backing pages. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c |2 ++ drivers/gpu/drm/i915/i915_drv.h |2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 229cf27..fd0ca3e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -125,6 +125,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) if (obj-gtt_space != NULL) seq_printf(m, (gtt offset: %08x, size: %08x), obj-gtt_offset, (unsigned int)obj-gtt_space-size); + if (obj-stolen) + seq_printf(m, (stolen: %08lx), obj-stolen-start); if (obj-pin_mappable || obj-fault_mappable) { char s[3], *t = s; if (obj-pin_mappable) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0fec169..d6cf758 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -908,6 +908,8 @@ struct drm_i915_gem_object { /** Current space allocated to this object in the GTT, if any. */ struct drm_mm_node *gtt_space; + /** Stolen memory for this object, instead of being backed by shmem. */ + struct drm_mm_node *stolen; struct list_head gtt_list; /** This object's place on the active/inactive lists */ -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 12/29] drm/i915: Replace the array of pages with a scatterlist
Rather than have multiple data structures for describing our page layout in conjunction with the array of pages, we can migrate all users over to a scatterlist. One major advantage, other than unifying the page tracking structures, this offers is that we replace the vmalloc'ed array (which can be up to a megabyte in size) with a chain of individual pages which helps reduce memory pressure. The disadvantage is that we then do not have a simple array to iterate, or to access randomly. The common case for this is in the relocation processing, which will typically fit within a single scatterlist page and so be almost the same cost as the simple array. For iterating over the array, the extra function call could be optimised away, but in reality is an insignificant cost of either binding the pages, or performing the pwrite/pread. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/char/agp/intel-gtt.c | 51 +--- drivers/gpu/drm/drm_cache.c| 23 ++ drivers/gpu/drm/i915/i915_drv.h| 18 +++-- drivers/gpu/drm/i915/i915_gem.c| 79 -- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 113 ++ drivers/gpu/drm/i915/i915_gem_execbuffer.c |3 +- drivers/gpu/drm/i915/i915_gem_gtt.c| 120 ++-- drivers/gpu/drm/i915/i915_gem_tiling.c | 16 ++-- drivers/gpu/drm/i915/i915_irq.c| 25 +++--- drivers/gpu/drm/i915/intel_ringbuffer.c|9 ++- include/drm/drmP.h |1 + include/drm/intel-gtt.h| 10 +-- 12 files changed, 250 insertions(+), 218 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 9ed92ef..1d39864 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -84,40 +84,33 @@ static struct _intel_private { #define IS_IRONLAKEintel_private.driver-is_ironlake #define HAS_PGTBL_EN intel_private.driver-has_pgtbl_enable -int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, -struct scatterlist **sg_list, int *num_sg) +static int intel_gtt_map_memory(struct page **pages, + unsigned int num_entries, + struct sg_table *st) { - struct sg_table st; struct scatterlist *sg; int i; - if (*sg_list) - return 0; /* already mapped (for e.g. resume */ - DBG(try mapping %lu pages\n, (unsigned long)num_entries); - if (sg_alloc_table(st, num_entries, GFP_KERNEL)) + if (sg_alloc_table(st, num_entries, GFP_KERNEL)) goto err; - *sg_list = sg = st.sgl; - - for (i = 0 ; i num_entries; i++, sg = sg_next(sg)) + for_each_sg(st-sgl, sg, num_entries,i) sg_set_page(sg, pages[i], PAGE_SIZE, 0); - *num_sg = pci_map_sg(intel_private.pcidev, *sg_list, -num_entries, PCI_DMA_BIDIRECTIONAL); - if (unlikely(!*num_sg)) + if (!pci_map_sg(intel_private.pcidev, + st-sgl, st-nents, PCI_DMA_BIDIRECTIONAL)) goto err; return 0; err: - sg_free_table(st); + sg_free_table(st); return -ENOMEM; } -EXPORT_SYMBOL(intel_gtt_map_memory); -void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) +static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) { struct sg_table st; DBG(try unmapping %lu pages\n, (unsigned long)mem-page_count); @@ -130,7 +123,6 @@ void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) sg_free_table(st); } -EXPORT_SYMBOL(intel_gtt_unmap_memory); static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) { @@ -879,8 +871,7 @@ static bool i830_check_flags(unsigned int flags) return false; } -void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, -unsigned int sg_len, +void intel_gtt_insert_sg_entries(struct sg_table *st, unsigned int pg_start, unsigned int flags) { @@ -892,12 +883,11 @@ void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, /* sg may merge pages, but we have to separate * per-page addr for GTT */ - for_each_sg(sg_list, sg, sg_len, i) { + for_each_sg(st-sgl, sg, st-nents, i) { len = sg_dma_len(sg) PAGE_SHIFT; for (m = 0; m len; m++) { dma_addr_t addr = sg_dma_address(sg) + (m PAGE_SHIFT); - intel_private.driver-write_entry(addr, - j, flags); + intel_private.driver-write_entry(addr, j, flags); j++; } } @@ -905,8 +895,10 @@ void
[Intel-gfx] [PATCH 10/29] drm/i915: Pin backing pages for pwrite
By using the recently introduced pinning of pages, we can safely drop the mutex in the knowledge that the pages are not going to disappear beneath us, and so we can simplify the code for iterating over the pages. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 37 + 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c90e265..2e5cecc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -690,7 +690,7 @@ shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, page_length); kunmap_atomic(vaddr); - return ret; + return ret ? -EFAULT : 0; } /* Only difference to the fast-path function is that this can handle bit17 @@ -724,7 +724,7 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, page_do_bit17_swizzling); kunmap(page); - return ret; + return ret ? -EFAULT : 0; } static int @@ -733,7 +733,6 @@ i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_i915_gem_pwrite *args, struct drm_file *file) { - struct address_space *mapping = obj-base.filp-f_path.dentry-d_inode-i_mapping; ssize_t remain; loff_t offset; char __user *user_data; @@ -742,7 +741,6 @@ i915_gem_shmem_pwrite(struct drm_device *dev, int hit_slowpath = 0; int needs_clflush_after = 0; int needs_clflush_before = 0; - int release_page; user_data = (char __user *) (uintptr_t) args-data_ptr; remain = args-size; @@ -768,6 +766,12 @@ i915_gem_shmem_pwrite(struct drm_device *dev, obj-cache_level == I915_CACHE_NONE) needs_clflush_before = 1; + ret = i915_gem_object_get_pages(obj); + if (ret) + return ret; + + i915_gem_object_pin_pages(obj); + offset = args-offset; obj-dirty = 1; @@ -793,18 +797,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, ((shmem_page_offset | page_length) (boot_cpu_data.x86_clflush_size - 1)); - if (obj-pages) { - page = obj-pages[offset PAGE_SHIFT]; - release_page = 0; - } else { - page = shmem_read_mapping_page(mapping, offset PAGE_SHIFT); - if (IS_ERR(page)) { - ret = PTR_ERR(page); - goto out; - } - release_page = 1; - } - + page = obj-pages[offset PAGE_SHIFT]; page_do_bit17_swizzling = obj_do_bit17_swizzling (page_to_phys(page) (1 17)) != 0; @@ -816,26 +809,20 @@ i915_gem_shmem_pwrite(struct drm_device *dev, goto next_page; hit_slowpath = 1; - page_cache_get(page); mutex_unlock(dev-struct_mutex); - ret = shmem_pwrite_slow(page, shmem_page_offset, page_length, user_data, page_do_bit17_swizzling, partial_cacheline_write, needs_clflush_after); mutex_lock(dev-struct_mutex); - page_cache_release(page); + next_page: set_page_dirty(page); mark_page_accessed(page); - if (release_page) - page_cache_release(page); - if (ret) { - ret = -EFAULT; + if (ret) goto out; - } remain -= page_length; user_data += page_length; @@ -843,6 +830,8 @@ next_page: } out: + i915_gem_object_unpin_pages(obj); + if (hit_slowpath) { /* Fixup: Kill any reinstated backing storage pages */ if (obj-madv == __I915_MADV_PURGED) -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 09/29] drm/i915: Pin backing pages whilst exporting through a dmabuf vmap
We need to refcount our pages in order to prevent reaping them at inopportune times, such as when they currently vmapped or exported to another driver. However, we also wish to keep the lazy deallocation of our pages so we need to take a pin/unpinned approach rather than a simple refcount. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h| 12 drivers/gpu/drm/i915/i915_gem.c| 11 +-- drivers/gpu/drm/i915/i915_gem_dmabuf.c |9 +++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c42190b..0805040f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -989,6 +989,7 @@ struct drm_i915_gem_object { unsigned int has_global_gtt_mapping:1; struct page **pages; + int pages_pin_count; /** * DMAR support @@ -1322,6 +1323,17 @@ void i915_gem_release_mmap(struct drm_i915_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); +static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) +{ + BUG_ON(obj-pages == NULL); + obj-pages_pin_count++; +} +static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) +{ + BUG_ON(obj-pages_pin_count == 0); + obj-pages_pin_count--; +} + int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); int i915_gem_object_sync(struct drm_i915_gem_object *obj, struct intel_ring_buffer *to); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ed6a1ec..c90e265 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1455,6 +1455,9 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) if (obj-sg_table || obj-pages == NULL) return 0; + if (obj-pages_pin_count) + return -EBUSY; + ops-put_pages(obj); list_del(obj-gtt_list); @@ -1586,6 +1589,8 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) if (obj-sg_table || obj-pages) return 0; + BUG_ON(obj-pages_pin_count); + ret = ops-get_pages(obj); if (ret) return ret; @@ -3685,6 +3690,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) dev_priv-mm.interruptible = was_interruptible; } + obj-pages_pin_count = 0; i915_gem_object_put_pages(obj); i915_gem_object_free_mmap_offset(obj); @@ -4344,9 +4350,10 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) cnt = 0; list_for_each_entry(obj, dev_priv-mm.unbound_list, gtt_list) - cnt += obj-base.size PAGE_SHIFT; + if (obj-pages_pin_count == 0) + cnt += obj-base.size PAGE_SHIFT; list_for_each_entry(obj, dev_priv-mm.bound_list, gtt_list) - if (obj-pin_count == 0) + if (obj-pin_count == 0 obj-pages_pin_count == 0) cnt += obj-base.size PAGE_SHIFT; mutex_unlock(dev-struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 1203460..4a6982e 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -50,6 +50,8 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme /* link the pages into an SG then map the sg */ sg = drm_prime_pages_to_sg(obj-pages, npages); nents = dma_map_sg(attachment-dev, sg-sgl, sg-nents, dir); + i915_gem_object_pin_pages(obj); + out: mutex_unlock(dev-struct_mutex); return sg; @@ -72,6 +74,7 @@ static void i915_gem_dmabuf_release(struct dma_buf *dma_buf) obj-base.export_dma_buf = NULL; drm_gem_object_unreference_unlocked(obj-base); } + i915_gem_object_unpin_pages(obj); } static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) @@ -102,6 +105,7 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) } obj-vmapping_count = 1; + i915_gem_object_pin_pages(obj); out_unlock: mutex_unlock(dev-struct_mutex); return obj-dma_buf_vmapping; @@ -117,10 +121,11 @@ static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) if (ret) return; - --obj-vmapping_count; - if (obj-vmapping_count == 0) { + if (--obj-vmapping_count == 0) { vunmap(obj-dma_buf_vmapping); obj-dma_buf_vmapping = NULL; + + i915_gem_object_unpin_pages(obj); } mutex_unlock(dev-struct_mutex); } -- 1.7.10.4 ___ Intel-gfx mailing list
[Intel-gfx] [PATCH 05/29] drm/i915: Only pwrite through the GTT if there is space in the aperture
Avoid stalling and waiting for the GPU by checking to see if there is sufficient inactive space in the aperture for us to bind the buffer prior to writing through the GTT. If there is inadequate space we will have to stall waiting for the GPU, and incur overheads moving objects about. Instead, only incur the clflush overhead on the target object by writing through shmem. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h|6 -- drivers/gpu/drm/i915/i915_gem.c| 29 +++- drivers/gpu/drm/i915/i915_gem_context.c|4 ++-- drivers/gpu/drm/i915/i915_gem_evict.c |6 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c |2 +- drivers/gpu/drm/i915/intel_overlay.c |2 +- drivers/gpu/drm/i915/intel_pm.c|2 +- drivers/gpu/drm/i915/intel_ringbuffer.c|6 +++--- 8 files changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e252947..78eed86 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1307,7 +1307,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, void i915_gem_free_object(struct drm_gem_object *obj); int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, uint32_t alignment, -bool map_and_fenceable); +bool map_and_fenceable, +bool nonblocking); void i915_gem_object_unpin(struct drm_i915_gem_object *obj); int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); @@ -1454,7 +1455,8 @@ void i915_gem_init_global_gtt(struct drm_device *dev, int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment, unsigned cache_level, - bool mappable); + bool mappable, + bool nonblock); int i915_gem_evict_everything(struct drm_device *dev); /* i915_gem_stolen.c */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0e0fc1e..b16b5ff 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -41,7 +41,8 @@ static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *o static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, unsigned alignment, - bool map_and_fenceable); + bool map_and_fenceable, + bool nonblocking); static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, @@ -609,7 +610,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, char __user *user_data; int page_offset, page_length, ret; - ret = i915_gem_object_pin(obj, 0, true); + ret = i915_gem_object_pin(obj, 0, true, true); if (ret) goto out; @@ -925,10 +926,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, goto out; } - if (obj-gtt_space - obj-cache_level == I915_CACHE_NONE + if (obj-cache_level == I915_CACHE_NONE obj-tiling_mode == I915_TILING_NONE - obj-map_and_fenceable obj-base.write_domain != I915_GEM_DOMAIN_CPU) { ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file); /* Note that the gtt paths might fail with non-page-backed user @@ -936,7 +935,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, * textures). Fallback to the shmem path in that case. */ } - if (ret == -EFAULT) + if (ret == -EFAULT || ret == -ENOSPC) ret = i915_gem_shmem_pwrite(dev, obj, args, file); out: @@ -1115,7 +1114,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) goto unlock; } if (!obj-gtt_space) { - ret = i915_gem_object_bind_to_gtt(obj, 0, true); + ret = i915_gem_object_bind_to_gtt(obj, 0, true, false); if (ret) goto unlock; @@ -2771,7 +2770,8 @@ static void i915_gem_verify_gtt(struct drm_device *dev) static int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, unsigned alignment, -
[Intel-gfx] [PATCH 04/29] drm/i915: Try harder to allocate an mmap_offset
Given the persistence of an offset for the lifetime of an object, itis easy to contemplate how the mmap space becomes badly fragmented to the point that further allocations fail with ENOSPC. Our only recourse at this point is to try to purge the objects to release some space and reattempt the allocation. References: https://bugs.freedesktop.org/show_bug.cgi?id=39552 Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 50 --- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3a7ac38..0e0fc1e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1276,6 +1276,42 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev, return i915_gem_get_gtt_size(dev, size, tiling_mode); } +static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = obj-base.dev-dev_private; + int ret; + + if (obj-base.map_list.map) + return 0; + + ret = drm_gem_create_mmap_offset(obj-base); + if (ret != -ENOSPC) + return ret; + + /* Badly fragmented mmap space? The only way we can recover +* space is by destroying unwanted objects. We can't randomly release +* mmap_offsets as userspace expects them to be persistent for the +* lifetime of the objects. The closest we can is to release the +* offsets on purgeable objects by truncating it and marking it purged, +* which prevents userspace from ever using that object again. +*/ + i915_gem_purge(dev_priv, obj-base.size PAGE_SHIFT); + ret = drm_gem_create_mmap_offset(obj-base); + if (ret != -ENOSPC) + return ret; + + i915_gem_shrink_all(dev_priv); + return drm_gem_create_mmap_offset(obj-base); +} + +static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj) +{ + if (!obj-base.map_list.map) + return; + + drm_gem_free_mmap_offset(obj-base); +} + int i915_gem_mmap_gtt(struct drm_file *file, struct drm_device *dev, @@ -1307,11 +1343,9 @@ i915_gem_mmap_gtt(struct drm_file *file, goto out; } - if (!obj-base.map_list.map) { - ret = drm_gem_create_mmap_offset(obj-base); - if (ret) - goto out; - } + ret = i915_gem_object_create_mmap_offset(obj); + if (ret) + goto out; *offset = (u64)obj-base.map_list.hash.key PAGE_SHIFT; @@ -1360,8 +1394,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) inode = obj-base.filp-f_path.dentry-d_inode; shmem_truncate_range(inode, 0, (loff_t)-1); - if (obj-base.map_list.map) - drm_gem_free_mmap_offset(obj-base); + i915_gem_object_free_mmap_offset(obj); obj-madv = __I915_MADV_PURGED; } @@ -3614,8 +3647,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) } i915_gem_object_put_pages_gtt(obj); - if (obj-base.map_list.map) - drm_gem_free_mmap_offset(obj-base); + i915_gem_object_free_mmap_offset(obj); drm_gem_object_release(obj-base); i915_gem_info_remove_obj(dev_priv, obj-base.size); -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 03/29] drm/i915: Show pin count in debugfs
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 16e8701..229cf27 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -118,6 +118,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj-madv == I915_MADV_DONTNEED ? purgeable : ); if (obj-base.name) seq_printf(m, (name: %d), obj-base.name); + if (obj-pin_count) + seq_printf(m, (pinned x %d), obj-pin_count); if (obj-fence_reg != I915_FENCE_REG_NONE) seq_printf(m, (fence: %d), obj-fence_reg); if (obj-gtt_space != NULL) -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 02/29] drm/i915: Show (count, size) of purgeable objects in i915_gem_objects
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a7eb093..16e8701 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -197,8 +197,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data) struct drm_info_node *node = (struct drm_info_node *) m-private; struct drm_device *dev = node-minor-dev; struct drm_i915_private *dev_priv = dev-dev_private; - u32 count, mappable_count; - size_t size, mappable_size; + u32 count, mappable_count, purgeable_count; + size_t size, mappable_size, purgeable_size; struct drm_i915_gem_object *obj; int ret; @@ -225,9 +225,12 @@ static int i915_gem_object_info(struct seq_file *m, void* data) seq_printf(m, %u [%u] inactive objects, %zu [%zu] bytes\n, count, mappable_count, size, mappable_size); - size = count = 0; - list_for_each_entry(obj, dev_priv-mm.unbound_list, gtt_list) + size = count = purgeable_size = purgeable_count = 0; + list_for_each_entry(obj, dev_priv-mm.unbound_list, gtt_list) { size += obj-base.size, ++count; + if (obj-madv == I915_MADV_DONTNEED) + purgeable_size += obj-base.size, ++purgeable_count; + } seq_printf(m, %u unbound objects, %zu bytes\n, count, size); size = count = mappable_size = mappable_count = 0; @@ -237,10 +240,16 @@ static int i915_gem_object_info(struct seq_file *m, void* data) ++count; } if (obj-pin_mappable) { - mappable_size += obj-gtt_space-size; + mappable_size += obj-gtt_space-size, ++mappable_count; } + if (obj-madv == I915_MADV_DONTNEED) { + purgeable_size += obj-base.size; + ++purgeable_count; + } } + seq_printf(m, %u purgeable objects, %zu bytes\n, + purgeable_count, purgeable_size); seq_printf(m, %u pinned mappable objects, %zu bytes\n, mappable_count, mappable_size); seq_printf(m, %u fault mappable objects, %zu bytes\n, -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 07/29] drm/i915: Extract general object init routine
As we wish to create specialised object constructions in the near future that share the same basic GEM object struct, export the default initializer. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h |1 + drivers/gpu/drm/i915/i915_gem.c | 30 ++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 78eed86..bbc51ef 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1302,6 +1302,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); int i915_gem_init_object(struct drm_gem_object *obj); +void i915_gem_object_init(struct drm_i915_gem_object *obj); struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size); void i915_gem_free_object(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2f4a113..9c8787e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3557,10 +3557,26 @@ unlock: return ret; } +void i915_gem_object_init(struct drm_i915_gem_object *obj) +{ + obj-base.driver_private = NULL; + + INIT_LIST_HEAD(obj-mm_list); + INIT_LIST_HEAD(obj-gtt_list); + INIT_LIST_HEAD(obj-ring_list); + INIT_LIST_HEAD(obj-exec_list); + + obj-fence_reg = I915_FENCE_REG_NONE; + obj-madv = I915_MADV_WILLNEED; + /* Avoid an unnecessary call to unbind on the first bind. */ + obj-map_and_fenceable = true; + + i915_gem_info_add_obj(obj-base.dev-dev_private, obj-base.size); +} + struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size) { - struct drm_i915_private *dev_priv = dev-dev_private; struct drm_i915_gem_object *obj; struct address_space *mapping; u32 mask; @@ -3584,7 +3600,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, mapping = obj-base.filp-f_path.dentry-d_inode-i_mapping; mapping_set_gfp_mask(mapping, mask); - i915_gem_info_add_obj(dev_priv, size); + i915_gem_object_init(obj); obj-base.write_domain = I915_GEM_DOMAIN_CPU; obj-base.read_domains = I915_GEM_DOMAIN_CPU; @@ -3606,16 +3622,6 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, } else obj-cache_level = I915_CACHE_NONE; - obj-base.driver_private = NULL; - obj-fence_reg = I915_FENCE_REG_NONE; - INIT_LIST_HEAD(obj-mm_list); - INIT_LIST_HEAD(obj-gtt_list); - INIT_LIST_HEAD(obj-ring_list); - INIT_LIST_HEAD(obj-exec_list); - obj-madv = I915_MADV_WILLNEED; - /* Avoid an unnecessary call to unbind on the first bind. */ - obj-map_and_fenceable = true; - return obj; } -- 1.7.10.4 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 01/29] drm/i915: Track unbound pages
When dealing with a working set larger than the GATT, or even the mappable aperture when touching through the GTT, we end up with evicting objects only to rebind them at a new offset again later. Moving an object into and out of the GTT requires clflushing the pages, thus causing a double-clflush penalty for rebinding. To avoid having to clflush on rebinding, we can track the pages as they are evicted from the GTT and only relinquish those pages on memory pressure. As usual, if it were not for the handling of out-of-memory condition and having to manually shrink our own bo caches, it would be a net reduction of code. Alas. Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c| 14 +- drivers/gpu/drm/i915/i915_drv.h| 13 +- drivers/gpu/drm/i915/i915_gem.c| 397 ++-- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 20 +- drivers/gpu/drm/i915/i915_gem_evict.c | 13 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c |9 +- drivers/gpu/drm/i915/i915_gem_gtt.c|2 +- drivers/gpu/drm/i915/i915_irq.c|4 +- drivers/gpu/drm/i915/i915_trace.h | 10 +- 9 files changed, 240 insertions(+), 242 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0e8f14d..a7eb093 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -211,7 +211,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) dev_priv-mm.object_memory); size = count = mappable_size = mappable_count = 0; - count_objects(dev_priv-mm.gtt_list, gtt_list); + count_objects(dev_priv-mm.bound_list, gtt_list); seq_printf(m, %u [%u] objects, %zu [%zu] bytes in gtt\n, count, mappable_count, size, mappable_size); @@ -225,8 +225,13 @@ static int i915_gem_object_info(struct seq_file *m, void* data) seq_printf(m, %u [%u] inactive objects, %zu [%zu] bytes\n, count, mappable_count, size, mappable_size); + size = count = 0; + list_for_each_entry(obj, dev_priv-mm.unbound_list, gtt_list) + size += obj-base.size, ++count; + seq_printf(m, %u unbound objects, %zu bytes\n, count, size); + size = count = mappable_size = mappable_count = 0; - list_for_each_entry(obj, dev_priv-mm.gtt_list, gtt_list) { + list_for_each_entry(obj, dev_priv-mm.bound_list, gtt_list) { if (obj-fault_mappable) { size += obj-gtt_space-size; ++count; @@ -264,7 +269,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data) return ret; total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj, dev_priv-mm.gtt_list, gtt_list) { + list_for_each_entry(obj, dev_priv-mm.bound_list, gtt_list) { if (list == PINNED_LIST obj-pin_count == 0) continue; @@ -526,7 +531,8 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) for (i = 0; i dev_priv-num_fence_regs; i++) { struct drm_i915_gem_object *obj = dev_priv-fence_regs[i].obj; - seq_printf(m, Fenced object[%2d] = , i); + seq_printf(m, Fence %d, pin count = %d, object = , + i, dev_priv-fence_regs[i].pin_count); if (obj == NULL) seq_printf(m, unused); else diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 261fe21..e252947 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -692,7 +692,13 @@ typedef struct drm_i915_private { struct drm_mm gtt_space; /** List of all objects in gtt_space. Used to restore gtt * mappings on resume */ - struct list_head gtt_list; + struct list_head bound_list; + /** +* List of objects which are not bound to the GTT (thus +* are idle and not used by the GPU) but still have +* (presumably uncached) pages still attached. +*/ + struct list_head unbound_list; /** Usable portion of the GTT for GEM */ unsigned long gtt_start; @@ -1307,8 +1313,7 @@ int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); -int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, - gfp_t gfpmask); +int __must_check i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj); int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); int i915_gem_object_sync(struct drm_i915_gem_object *obj,
Re: [Intel-gfx] Macbook Air 2012
Dear Daniel, Am Samstag, den 11.08.2012, 16:05 +0200 schrieb Daniel Wagner: I installed on my shiny new Macbook Air 2012 Fedora 17. After adding intremap=off to the kernel arguments, I was able to install the system. The X server worked out of the box. This was with a 3.3.4 kernel. Then I started to upgrade the installation and a newer kernel was installed 3.5. After the reboot the screen stayed black. Upgrading to Linus' 3.6-rc1 didn't help either. After some research I have tried now Daniel's tree danvet branch drm-intel-next. Still no success. I also found https://bugs.freedesktop.org/show_bug.cgi?id=48652 which sounds awfully like what I am seeing as symptoms. Unfortunately, is my graphic trouble debugging skills rather limited. Is there anything I could provide to resolve this issue? I think there is a fix already [1]. […] Thanks, Paul [1] http://lists.freedesktop.org/archives/intel-gfx/2012-August/019545.html signature.asc Description: This is a digitally signed message part ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] Fan constantly running with Intel Graphics card
On Fri, 10 Aug 2012 14:28:35 + (UTC) Patrick O'Byrne pobyr...@gmail.com wrote: Hi, I am having an issue with a new Dell E5520 laptop (Intel(R) Core(TM) i5-2520 CPU @ 2.5GHz) running Linux Mint 13 (Kernel: Linux 3.2.0-23-generic (i686)). I am using the graphics driver that ships with the kernel: 00:02.0 VGA compatible controller [0300]: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller [8086:0126] (rev 09) My problem is that the fan is constantly on even though I am not doing any intensive processing. The laptop runs very nicely (quietly) when I boot into Windows 7. There was a recent post which suggests running the following commands: $ cat /sys/kernel/debug/dri/0/i915_cur_delayinfo | grep Lowest then echo that value into the max freq file, e.g.: $ echo 400 /sys/kernel/debug/dri/0/i915_max_freq I tried this (and restarted the machine) but still no joy, it seems that in my case GPU frequency is not to blame. Any advice would be greatly appreciated. Regards Patrick Can you please try sysfs_rc6_residency test in intel-gpu-tools? This might be the same issue I am currently fighting. -- Ben Widawsky, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Apply post-sync write for pipe control invalidates
On Fri, 10 Aug 2012 10:18:10 +0100 Chris Wilson ch...@chris-wilson.co.uk wrote: When invalidating the TLBs it is documentated as requiring a post-sync write. Failure to do so seems to result in a GPU hang. Exposure to this hang on IVB seems to be a result of removing the extra stalls required for SNB pipecontrol workarounds: commit 6c6cf5aa9c583478b19e23149feaa92d01fb8c2d Author: Chris Wilson ch...@chris-wilson.co.uk Date: Fri Jul 20 18:02:28 2012 +0100 drm/i915: Only apply the SNB pipe control w/a to gen6 Reported-by: yex.t...@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=53322 Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk This is the moral equivalent of my patch to make the simulator happy on IVB. Daniel, I'll settle for either patch. Therefore, Acked-by: Ben Widawsky b...@bwidawsk.net --- drivers/gpu/drm/i915/intel_ringbuffer.c | 35 ++- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 13318a0..7608bc2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -213,20 +213,27 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, * number of bits based on the write domains has little performance * impact. */ - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_TLB_INVALIDATE; - flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; - flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - /* - * Ensure that any following seqno writes only happen when the render - * cache is indeed flushed (but only if the caller actually wants that). - */ - if (flush_domains) + if (flush_domains) { + flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; + flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + /* + * Ensure that any following seqno writes only happen + * when the render cache is indeed flushed. + */ flags |= PIPE_CONTROL_CS_STALL; + } + if (invalidate_domains) { + flags |= PIPE_CONTROL_TLB_INVALIDATE; + flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; + /* + * TLB invalidate requires a post-sync write. + */ + flags |= PIPE_CONTROL_QW_WRITE; + } ret = intel_ring_begin(ring, 4); if (ret) @@ -234,7 +241,7 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); intel_ring_emit(ring, flags); - intel_ring_emit(ring, 0); + intel_ring_emit(ring, (u32)ring-status_page.gfx_addr+2048); intel_ring_emit(ring, 0); intel_ring_advance(ring); -- Ben Widawsky, Intel Open Source Technology Center ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: ingore eDP bpc settings
On Fri, Aug 10, 2012 at 12:24:29PM +0200, Benoit Gschwind wrote: Hello, I confirm this patch work apply to kernel 3.6-rc1 Ok, I've picked this up for -fixes, with the commit message a bit improved. Let's see whether this blows up anywhere. -Daniel -- Daniel Vetter Mail: dan...@ffwll.ch Mobile: +41 (0)79 365 57 48 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: Apply post-sync write for pipe control invalidates
On Sat, Aug 11, 2012 at 12:20:19PM -0700, Ben Widawsky wrote: On Fri, 10 Aug 2012 10:18:10 +0100 Chris Wilson ch...@chris-wilson.co.uk wrote: When invalidating the TLBs it is documentated as requiring a post-sync write. Failure to do so seems to result in a GPU hang. Exposure to this hang on IVB seems to be a result of removing the extra stalls required for SNB pipecontrol workarounds: commit 6c6cf5aa9c583478b19e23149feaa92d01fb8c2d Author: Chris Wilson ch...@chris-wilson.co.uk Date: Fri Jul 20 18:02:28 2012 +0100 drm/i915: Only apply the SNB pipe control w/a to gen6 Reported-by: yex.t...@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=53322 Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk This is the moral equivalent of my patch to make the simulator happy on IVB. Daniel, I'll settle for either patch. Therefore, Acked-by: Ben Widawsky b...@bwidawsk.net Ok, I'll wait until we have testing feedback from the bug report and then either merge this to -fixes or -next. -Daniel -- Daniel Vetter Mail: dan...@ffwll.ch Mobile: +41 (0)79 365 57 48 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: don't grab dev-struct_mutex for userspace forcewak
On Fri, Aug 10, 2012 at 11:22:15PM +0100, Chris Wilson wrote: On Thu, 9 Aug 2012 22:33:58 +0200, Daniel Vetter daniel.vet...@ffwll.ch wrote: Since forcewake is now protected by a spinlock, we don't need to grab dev-struct_mutex any more. This way we can also get rid of a stale comment, noticed by Ben Widawsky while reviewing some locking changes. Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch Reviewed-by: Chris Wilson ch...@chris-wilson.co.uk (Although I still wish it were not so) Queued for -next, thanks for the review. -Daniel -- Daniel Vetter Mail: dan...@ffwll.ch Mobile: +41 (0)79 365 57 48 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] Macbook Air 2012
On Sat, Aug 11, 2012 at 04:48:15PM +0200, Paul Menzel wrote: Dear Daniel, Am Samstag, den 11.08.2012, 16:05 +0200 schrieb Daniel Wagner: I installed on my shiny new Macbook Air 2012 Fedora 17. After adding intremap=off to the kernel arguments, I was able to install the system. The X server worked out of the box. This was with a 3.3.4 kernel. Then I started to upgrade the installation and a newer kernel was installed 3.5. After the reboot the screen stayed black. Upgrading to Linus' 3.6-rc1 didn't help either. After some research I have tried now Daniel's tree danvet branch drm-intel-next. Still no success. I also found https://bugs.freedesktop.org/show_bug.cgi?id=48652 which sounds awfully like what I am seeing as symptoms. Unfortunately, is my graphic trouble debugging skills rather limited. Is there anything I could provide to resolve this issue? I think there is a fix already [1]. Nope, that's the fix for the new retina macbook pro. Daniel, if you can, please test the latest patch attached to that bug report and reply on the bug report with the result. Thanks, Daniel -- Daniel Vetter Mail: dan...@ffwll.ch Mobile: +41 (0)79 365 57 48 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx