From 4661270797f0c172da4b54415574421cd27f1bf3 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 25 May 2014 12:24:42 +0200 Subject: [PATCH 1/8] drm/i915: use shmem helpers if possible Instead of shuffling gfp-masks all the time, use the shmem_read_mapping_page() helper. Note that __GFP_IO and __GFP_WAIT are set in mapping_gfp_mask() for i915, so the behavior is still the same. Cc: Daniel Vetter Cc: Jani Nikula Signed-off-by: David Herrmann --- drivers/gpu/drm/i915/i915_gem.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f36126383d26..d86b77e905a2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2059,16 +2059,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * our own buffer, now let the real VM do its job and * go down in flames if truly OOM. */ - gfp &= ~(__GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD); - gfp |= __GFP_IO | __GFP_WAIT; - i915_gem_shrink_all(dev_priv); - page = shmem_read_mapping_page_gfp(mapping, i, gfp); + page = shmem_read_mapping_page(mapping, i); if (IS_ERR(page)) goto err_pages; - - gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD; - gfp &= ~(__GFP_IO | __GFP_WAIT); } #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { From ab5a60c3ee41ff22304e2bcf63c151aa2851df0c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 25 May 2014 12:45:39 +0200 Subject: [PATCH 2/8] drm/omap: use __GFP_DMA32 for shmem-backed gem OMAP requires bo-pages to be in the DMA32 zone. Explicitly request this by setting __GFP_DMA32 as mapping-gfp-mask during shmem initialization. This drops HIGHMEM from the gfp-mask and uses DMA32 instead. shmem-core takes care to relocate pages during swap-in in case they have been loaded into the wrong zone. It is _not_ possible to pass __GFP_DMA32 to shmem_read_mapping_page_gfp() as the page might have already been swapped-in at that time. The zone-mask must be set during initialization and be kept constant for now. Remove the now superfluous TODO in omap_gem.c. Reviewed-by: Rob Clark Tested-by: Tomi Valkeinen Signed-off-by: David Herrmann --- drivers/gpu/drm/omapdrm/omap_gem.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 95dbce286a41..1331fd538398 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -233,10 +233,6 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) WARN_ON(omap_obj->pages); - /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the - * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably - * we actually want CMA memory for it all anyways.. - */ pages = drm_gem_get_pages(obj, GFP_KERNEL); if (IS_ERR(pages)) { dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); @@ -1347,6 +1343,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, struct omap_drm_private *priv = dev->dev_private; struct omap_gem_object *omap_obj; struct drm_gem_object *obj = NULL; + struct address_space *mapping; size_t size; int ret; @@ -1404,14 +1401,16 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, omap_obj->height = gsize.tiled.height; } - ret = 0; - if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) + if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) { drm_gem_private_object_init(dev, obj, size); - else + } else { ret = drm_gem_object_init(dev, obj, size); + if (ret) + goto fail; - if (ret) - goto fail; + mapping = file_inode(obj->filp)->i_mapping; + mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32); + } return obj; From 0cdbe8ac696b5399327f972a1c91263c1a44f1d9 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 25 May 2014 12:59:47 +0200 Subject: [PATCH 3/8] drm/gem: remove misleading gfp parameter to get_pages() drm_gem_get_pages() currently allows passing a 'gfp' parameter that is passed to shmem combined with mapping_gfp_mask(). Given that the default mapping_gfp_mask() is GFP_HIGHUSER, it is _very_ unlikely that anyone will ever make use of that parameter. In fact, all drivers currently pass redundant flags or 0. This patch removes the 'gfp' parameter. The only reason to keep it is to remove flags like __GFP_WAIT. But in its current form, it can only be used to add flags. So to remove __GFP_WAIT, you'd have to drop it from the mapping_gfp_mask, which again is stupid as this mask is used by shmem-core for other allocations, too. If any driver ever requires that parameter, we can introduce a new helper that takes the raw 'gfp' parameter. The caller'd be responsible to combine it with mapping_gfp_mask() in a suitable way. The current drm_gem_get_pages() helper would then simply use mapping_gfp_mask() and call the new helper. This is what shmem_read_mapping_pages{_gfp,} does right now. Moreover, the gfp-zone flag-usage is not obvious: If you pass a modified zone, shmem core will WARN() or even BUG(). In other words, the following must be true for 'gfp' passed to shmem_read_mapping_pages_gfp(): gfp_zone(mapping_gfp_mask(mapping)) == gfp_zone(gfp) Add a comment to drm_gem_read_pages() explaining that constraint. Signed-off-by: David Herrmann --- drivers/gpu/drm/drm_gem.c | 29 ++++++++++++++++++++--------- drivers/gpu/drm/gma500/gtt.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 2 +- drivers/gpu/drm/omapdrm/omap_gem.c | 2 +- drivers/gpu/drm/udl/udl_gem.c | 8 ++++---- include/drm/drmP.h | 2 +- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index f7d71190aad5..6adee4c2afc0 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -441,18 +441,31 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset); * drm_gem_get_pages - helper to allocate backing pages for a GEM object * from shmem * @obj: obj in question - * @gfpmask: gfp mask of requested pages + * + * This reads the page-array of the shmem-backing storage of the given gem + * object. An array of pages is returned. If a page is not allocated or + * swapped-out, this will allocate/swap-in the required pages. Note that the + * whole object is covered by the page-array and pinned in memory. + * + * Use drm_gem_put_pages() to release the array and unpin all pages. + * + * This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()). + * If you require other GFP-masks, you have to do those allocations yourself. + * + * Note that you are not allowed to change gfp-zones during runtime. That is, + * shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as + * set during initialization. If you have special zone constraints, set them + * after drm_gem_init_object() via mapping_set_gfp_mask(). shmem-core takes care + * to keep pages in the required zone during swap-in. */ -struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) +struct page **drm_gem_get_pages(struct drm_gem_object *obj) { - struct inode *inode; struct address_space *mapping; struct page *p, **pages; int i, npages; /* This is the shared memory object that backs the GEM resource */ - inode = file_inode(obj->filp); - mapping = inode->i_mapping; + mapping = file_inode(obj->filp)->i_mapping; /* We already BUG_ON() for non-page-aligned sizes in * drm_gem_object_init(), so we should never hit this unless @@ -466,10 +479,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) if (pages == NULL) return ERR_PTR(-ENOMEM); - gfpmask |= mapping_gfp_mask(mapping); - for (i = 0; i < npages; i++) { - p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); + p = shmem_read_mapping_page(mapping, i); if (IS_ERR(p)) goto fail; pages[i] = p; @@ -479,7 +490,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) * __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping) * so shmem can relocate pages during swapin if required. */ - BUG_ON((gfpmask & __GFP_DMA32) && + BUG_ON((mapping_gfp_mask(mapping) & __GFP_DMA32) && (page_to_pfn(p) >= 0x00100000UL)); } diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 592d205a0089..ce015db59dc6 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -206,7 +206,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt) WARN_ON(gt->pages); - pages = drm_gem_get_pages(>->gem, 0); + pages = drm_gem_get_pages(>->gem); if (IS_ERR(pages)) return PTR_ERR(pages); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index bb8026daebc9..6866879efa3b 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -73,7 +73,7 @@ static struct page **get_pages(struct drm_gem_object *obj) int npages = obj->size >> PAGE_SHIFT; if (iommu_present(&platform_bus_type)) - p = drm_gem_get_pages(obj, 0); + p = drm_gem_get_pages(obj); else p = get_pages_vram(obj, npages); diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 1331fd538398..7c68c8a18939 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -233,7 +233,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) WARN_ON(omap_obj->pages); - pages = drm_gem_get_pages(obj, GFP_KERNEL); + pages = drm_gem_get_pages(obj); if (IS_ERR(pages)) { dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); return PTR_ERR(pages); diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index c041cd73f399..8044f5fb7c49 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -107,14 +107,14 @@ int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } } -static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask) +static int udl_gem_get_pages(struct udl_gem_object *obj) { struct page **pages; if (obj->pages) return 0; - pages = drm_gem_get_pages(&obj->base, gfpmask); + pages = drm_gem_get_pages(&obj->base); if (IS_ERR(pages)) return PTR_ERR(pages); @@ -147,7 +147,7 @@ int udl_gem_vmap(struct udl_gem_object *obj) return 0; } - ret = udl_gem_get_pages(obj, GFP_KERNEL); + ret = udl_gem_get_pages(obj); if (ret) return ret; @@ -205,7 +205,7 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, } gobj = to_udl_bo(obj); - ret = udl_gem_get_pages(gobj, GFP_KERNEL); + ret = udl_gem_get_pages(gobj); if (ret) goto out; ret = drm_gem_create_mmap_offset(obj); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8af71a8e2c00..57c07cd89a6a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1574,7 +1574,7 @@ void drm_gem_free_mmap_offset(struct drm_gem_object *obj); int drm_gem_create_mmap_offset(struct drm_gem_object *obj); int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size); -struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); +struct page **drm_gem_get_pages(struct drm_gem_object *obj); void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, bool dirty, bool accessed); From 15f8f65751f081bd2d57627c453fe8986a3a0718 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 17 Jun 2014 15:39:18 +0900 Subject: [PATCH 4/8] drm/ttm: remove declaration of ttm_tt_cache_flush ttm_tt_cache_flush's implementation was removed in 2009 by commit c9c97b8c, but its declaration has been hiding in ttm_bo_driver.h since then. It has been surviving in the dark for too long now ; give it the mercy blow. Reviewed-by: Thierry Reding Reviewed-by: David Herrmann Signed-off-by: Alexandre Courbot Signed-off-by: David Herrmann --- include/drm/ttm/ttm_bo_driver.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index a5183da3ef92..e3f8c99a8a9d 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -652,18 +652,6 @@ extern void ttm_tt_unbind(struct ttm_tt *ttm); */ extern int ttm_tt_swapin(struct ttm_tt *ttm); -/** - * ttm_tt_cache_flush: - * - * @pages: An array of pointers to struct page:s to flush. - * @num_pages: Number of pages to flush. - * - * Flush the data of the indicated pages from the cpu caches. - * This is used when changing caching attributes of the pages from - * cache-coherent. - */ -extern void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages); - /** * ttm_tt_set_placement_caching: * From 6d6dfcfb883818b40b58bac61cc72cab428a7a03 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 16 Mar 2014 14:38:40 +0100 Subject: [PATCH 5/8] drm: enable render-nodes by default We introduced render-nodes about 1/2 year ago and no problems showed up. Remove the drm_rnodes argument and enable them by default now. Acked-by: Daniel Vetter Acked-by: Alex Deucher Signed-off-by: David Herrmann --- drivers/gpu/drm/drm_stub.c | 7 +------ include/drm/drmP.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 14d16464000a..07bf70121e9a 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -37,9 +37,6 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); -unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */ -EXPORT_SYMBOL(drm_rnodes); - /* 1 to allow user space to request universal planes (experimental) */ unsigned int drm_universal_planes = 0; EXPORT_SYMBOL(drm_universal_planes); @@ -60,13 +57,11 @@ MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); -MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); module_param_named(debug, drm_debug, int, 0600); -module_param_named(rnodes, drm_rnodes, int, 0600); module_param_named(universal_planes, drm_universal_planes, int, 0600); module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); @@ -588,7 +583,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, goto err_minors; } - if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { + if (drm_core_check_feature(dev, DRIVER_RENDER)) { ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); if (ret) goto err_minors; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 57c07cd89a6a..dc74c971b992 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1395,7 +1395,6 @@ extern void drm_master_put(struct drm_master **master); extern void drm_put_dev(struct drm_device *dev); extern void drm_unplug_dev(struct drm_device *dev); extern unsigned int drm_debug; -extern unsigned int drm_rnodes; extern unsigned int drm_universal_planes; extern unsigned int drm_vblank_offdelay; From 2fc2dd781bec793fbc293ecc9345b233783a6382 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 27 Jun 2014 20:29:09 +0900 Subject: [PATCH 6/8] drm/ttm: recognize ARM arch in ioprot handler Nouveau can now be used on ARM, so add an ioprot handler for this architecture. Signed-off-by: Lucas Stach Signed-off-by: Alexandre Courbot Signed-off-by: David Herrmann --- drivers/gpu/drm/ttm/ttm_bo_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 1df856f78568..30e5d90cb7bc 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -500,7 +500,7 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) pgprot_val(tmp) |= _PAGE_GUARDED; } #endif -#if defined(__ia64__) +#if defined(__ia64__) || defined(__arm__) if (caching_flags & TTM_PL_FLAG_WC) tmp = pgprot_writecombine(tmp); else From a8ba29cd337cce06899e1ad51c69b4beea7628a0 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Tue, 1 Jul 2014 21:02:03 +0200 Subject: [PATCH 7/8] drm/bochs: replace ALIGN(PAGE_SIZE) by PAGE_ALIGN use mm.h definition Signed-off-by: Fabian Frederick Signed-off-by: David Herrmann --- drivers/gpu/drm/bochs/bochs_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index b9a695d92792..1728a1b0b813 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -387,7 +387,7 @@ int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel, *obj = NULL; - size = ALIGN(size, PAGE_SIZE); + size = PAGE_ALIGN(size); if (size == 0) return -EINVAL; From d2c87e2d2377966450cfb4271694c77dac615f98 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Fri, 4 Jul 2014 21:17:15 +0200 Subject: [PATCH 8/8] drm/omap: remove null test before kfree Fix checkpatch warning: WARNING: kfree(NULL) is safe this check is probably not required Cc: David Airlie Cc: Tomi Valkeinen Signed-off-by: Fabian Frederick Signed-off-by: David Herrmann --- drivers/gpu/drm/omapdrm/omap_gem.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 7c68c8a18939..5c3670017a4a 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1179,9 +1179,7 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op) } } spin_unlock(&sync_lock); - - if (waiter) - kfree(waiter); + kfree(waiter); } return ret; }