From 06e5598fce5ce89fe8bf081398296e5b08d993dd Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 18 Dec 2012 10:31:26 -0800 Subject: drm/i915: Move GSM mapping into dev_priv This removes an unused field from the AGP structure and moves it into the dev_priv structure (with a slightly better name). This builds upon the kill-agp series already merged. GSM is a well defined term in the bspec: GSM: Graphics Stolen Memory GTT stolen space is defined for storage of the GFX GTT entries in physical memory. IA can not access GSM directly , it can only access via GTTMMADR. GT can access GSM directly or through GTTMMADR. This is not the entire stolen space. Signed-off-by: Ben Widawsky Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index dbd901e94ea6..c8d9dcb15db0 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -602,7 +602,6 @@ static int intel_gtt_init(void) iounmap(intel_private.registers); return -ENOMEM; } - intel_private.base.gtt = intel_private.gtt; global_cache_flush(); /* FIXME: ? */ -- cgit 1.4.1 From a81cc00c11ab6816fbcb7dd99a60b50e71765d25 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:31 -0800 Subject: drm/i915: Cut out the infamous ILK w/a from AGP layer And, move it to where the rest of the logic is. There is some slight functionality changes. There was extra paranoid checks in AGP code making sure we never do idle maps on gen2 parts. That was not duplicated as the simple PCI id check should do the right thing. v2: use IS_GEN5 && IS_MOBILE check instead. For now, this is the same as IS_IRONLAKE_M but is more future proof. The workaround docs hint that more than one platform may be effected, but we've never seen such a platform in the wild. (Rodrigo, Daniel) Reviewed-by: Rodrigo Vivi (v1) Cc: Dave Airlie Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 27 --------------------------- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem_gtt.c | 24 +++++++++++++++++++++--- include/drm/intel-gtt.h | 2 -- 4 files changed, 23 insertions(+), 32 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index c8d9dcb15db0..12c31026eb56 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -840,9 +840,6 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, { int ret = -EINVAL; - if (intel_private.base.do_idle_maps) - return -ENODEV; - if (intel_private.clear_fake_agp) { int start = intel_private.base.stolen_size / PAGE_SIZE; int end = intel_private.base.gtt_mappable_entries; @@ -907,9 +904,6 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, if (mem->page_count == 0) return 0; - if (intel_private.base.do_idle_maps) - return -ENODEV; - intel_gtt_clear_range(pg_start, mem->page_count); if (intel_private.base.needs_dmar) { @@ -1069,24 +1063,6 @@ static void i965_write_entry(dma_addr_t addr, writel(addr | pte_flags, intel_private.gtt + entry); } -/* Certain Gen5 chipsets require require idling the GPU before - * unmapping anything from the GTT when VT-d is enabled. - */ -static inline int needs_idle_maps(void) -{ -#ifdef CONFIG_INTEL_IOMMU - const unsigned short gpu_devid = intel_private.pcidev->device; - - /* Query intel_iommu to see if we need the workaround. Presumably that - * was loaded first. - */ - if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || - gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && - intel_iommu_gfx_mapped) - return 1; -#endif - return 0; -} static int i9xx_setup(void) { @@ -1115,9 +1091,6 @@ static int i9xx_setup(void) break; } - if (needs_idle_maps()) - intel_private.base.do_idle_maps = 1; - intel_i9xx_setup_flush(); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0a2a18b8a075..1fe802f4df13 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -381,6 +381,8 @@ struct i915_gtt { /** "Graphics Stolen Memory" holds the global PTEs */ void __iomem *gsm; + + bool do_idle_maps; }; #define I915_PPGTT_PD_ENTRIES 512 diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0f0db02c1e56..84c521fd11a2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -338,11 +338,27 @@ void i915_gem_init_ppgtt(struct drm_device *dev) } } +extern int intel_iommu_gfx_mapped; +/* Certain Gen5 chipsets require require idling the GPU before + * unmapping anything from the GTT when VT-d is enabled. + */ +static inline bool needs_idle_maps(struct drm_device *dev) +{ +#ifdef CONFIG_INTEL_IOMMU + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. + */ + if (IS_GEN5(dev) && IS_MOBILE(dev) && intel_iommu_gfx_mapped) + return true; +#endif + return false; +} + static bool do_idling(struct drm_i915_private *dev_priv) { bool ret = dev_priv->mm.interruptible; - if (unlikely(dev_priv->mm.gtt->do_idle_maps)) { + if (unlikely(dev_priv->gtt.do_idle_maps)) { dev_priv->mm.interruptible = false; if (i915_gpu_idle(dev_priv->dev)) { DRM_ERROR("Couldn't idle GPU\n"); @@ -356,11 +372,10 @@ static bool do_idling(struct drm_i915_private *dev_priv) static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) { - if (unlikely(dev_priv->mm.gtt->do_idle_maps)) + if (unlikely(dev_priv->gtt.do_idle_maps)) dev_priv->mm.interruptible = interruptible; } - static void i915_ggtt_clear_range(struct drm_device *dev, unsigned first_entry, unsigned num_entries) @@ -709,6 +724,9 @@ int i915_gem_gtt_init(struct drm_device *dev) intel_gmch_remove(); return -ENODEV; } + + dev_priv->gtt.do_idle_maps = needs_idle_maps(dev); + return 0; } diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 3e3a166a2690..1747aa095f41 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -13,8 +13,6 @@ struct intel_gtt { unsigned int gtt_mappable_entries; /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; - /* Whether we idle the gpu before mapping/unmapping */ - unsigned int do_idle_maps : 1; /* Share the scratch page dma with ppgtts. */ dma_addr_t scratch_page_dma; struct page *scratch_page; -- cgit 1.4.1 From 9c61a32d31a55c8c6e590d83ae5645e14fde09f2 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:32 -0800 Subject: drm/i915: Remove scratch page from shared We already had a mapping in both (minus the phys_addr in AGP). Reviewed-by: Rodrigo Vivi Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 9 +++++---- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem_gtt.c | 16 ++++++++-------- include/drm/intel-gtt.h | 3 --- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 12c31026eb56..7fcee5c2e986 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -75,6 +75,7 @@ static struct _intel_private { struct resource ifp_resource; int resource_valid; struct page *scratch_page; + phys_addr_t scratch_page_dma; int refcount; } intel_private; @@ -297,9 +298,9 @@ static int intel_gtt_setup_scratch_page(void) if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) return -EINVAL; - intel_private.base.scratch_page_dma = dma_addr; + intel_private.scratch_page_dma = dma_addr; } else - intel_private.base.scratch_page_dma = page_to_phys(page); + intel_private.scratch_page_dma = page_to_phys(page); intel_private.scratch_page = page; @@ -546,7 +547,7 @@ static unsigned int intel_gtt_mappable_entries(void) static void intel_gtt_teardown_scratch_page(void) { set_pages_wb(intel_private.scratch_page, 1); - pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma, + pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); put_page(intel_private.scratch_page); __free_page(intel_private.scratch_page); @@ -891,7 +892,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) unsigned int i; for (i = first_entry; i < (first_entry + num_entries); i++) { - intel_private.driver->write_entry(intel_private.base.scratch_page_dma, + intel_private.driver->write_entry(intel_private.scratch_page_dma, i, 0); } readl(intel_private.gtt+i-1); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1fe802f4df13..3189034deeb8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -383,6 +383,8 @@ struct i915_gtt { void __iomem *gsm; bool do_idle_maps; + dma_addr_t scratch_page_dma; + struct page *scratch_page; }; #define I915_PPGTT_PD_ENTRIES 512 diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 84c521fd11a2..3c1f66ebc245 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -162,7 +162,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) } } - ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma; + ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; i915_ppgtt_clear_range(ppgtt, 0, ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); @@ -396,7 +396,7 @@ static void i915_ggtt_clear_range(struct drm_device *dev, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = pte_encode(dev, dev_priv->mm.gtt->scratch_page_dma, I915_CACHE_LLC); + scratch_pte = pte_encode(dev, dev_priv->gtt.scratch_page_dma, I915_CACHE_LLC); for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); @@ -659,8 +659,8 @@ static int setup_scratch_page(struct drm_device *dev) #else dma_addr = page_to_phys(page); #endif - dev_priv->mm.gtt->scratch_page = page; - dev_priv->mm.gtt->scratch_page_dma = dma_addr; + dev_priv->gtt.scratch_page = page; + dev_priv->gtt.scratch_page_dma = dma_addr; return 0; } @@ -668,11 +668,11 @@ static int setup_scratch_page(struct drm_device *dev) static void teardown_scratch_page(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - set_pages_wb(dev_priv->mm.gtt->scratch_page, 1); - pci_unmap_page(dev->pdev, dev_priv->mm.gtt->scratch_page_dma, + set_pages_wb(dev_priv->gtt.scratch_page, 1); + pci_unmap_page(dev->pdev, dev_priv->gtt.scratch_page_dma, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - put_page(dev_priv->mm.gtt->scratch_page); - __free_page(dev_priv->mm.gtt->scratch_page); + put_page(dev_priv->gtt.scratch_page); + __free_page(dev_priv->gtt.scratch_page); } static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 1747aa095f41..c787ee4c4c07 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -13,9 +13,6 @@ struct intel_gtt { unsigned int gtt_mappable_entries; /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; - /* Share the scratch page dma with ppgtts. */ - dma_addr_t scratch_page_dma; - struct page *scratch_page; /* needed for ioremap in drm/i915 */ phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -- cgit 1.4.1 From 8d2e630899165d413ae8a2adc36846ac0b71bada Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:33 -0800 Subject: drm/i915: Needs_dmar, not The reasoning behind our code taking two paths depending upon whether or not we may have been configured for IOMMU isn't clear to me. It should always be safe to use the pci mapping functions as they are designed to abstract the decision we were handling in i915. Aside from simpler code, removing another member for the intel_gtt struct is a nice motivation. I ran this by Chris, and he wasn't concerned about the extra kzalloc, and memory references vs. page_to_phys calculation in the case without IOMMU. v2: Update commit message v3: Remove needs_dmar addition from Zhenyu upstream This reverts (and then other stuff) commit 20652097dadd9a7fb4d652f25466299974bc78f9 Author: Zhenyu Wang Date: Thu Dec 13 23:47:47 2012 +0800 drm/i915: Fix missed needs_dmar setting Reviewed-by: Rodrigo Vivi (v2) Cc: Zhenyu Wang Signed-off-by: Ben Widawsky [danvet: Squash in follow-up fix to remove the bogus hunk which deleted the dma_mask configuration for gen6+.] Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 10 +++++---- drivers/gpu/drm/i915/i915_gem_gtt.c | 45 +++++++++++++------------------------ include/drm/intel-gtt.h | 2 -- 3 files changed, 22 insertions(+), 35 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 7fcee5c2e986..b45241479a56 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -77,6 +77,8 @@ static struct _intel_private { struct page *scratch_page; phys_addr_t scratch_page_dma; int refcount; + /* Whether i915 needs to use the dmar apis or not. */ + unsigned int needs_dmar : 1; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -292,7 +294,7 @@ static int intel_gtt_setup_scratch_page(void) get_page(page); set_pages_uc(page, 1); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { dma_addr = pci_map_page(intel_private.pcidev, page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) @@ -608,7 +610,7 @@ static int intel_gtt_init(void) intel_private.base.stolen_size = intel_gtt_stolen_size(); - intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; + intel_private.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; ret = intel_gtt_setup_scratch_page(); if (ret != 0) { @@ -866,7 +868,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, if (!mem->is_flushed) global_cache_flush(); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { struct sg_table st; ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st); @@ -907,7 +909,7 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, intel_gtt_clear_range(pg_start, mem->page_count); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { intel_gtt_unmap_memory(mem->sg_list, mem->num_sg); mem->sg_list = NULL; mem->num_sg = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3c1f66ebc245..a0ba4a9e53c7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -138,28 +138,23 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) goto err_pt_alloc; } - if (dev_priv->mm.gtt->needs_dmar) { - ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) - *ppgtt->num_pd_entries, - GFP_KERNEL); - if (!ppgtt->pt_dma_addr) - goto err_pt_alloc; + ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, + GFP_KERNEL); + if (!ppgtt->pt_dma_addr) + goto err_pt_alloc; - for (i = 0; i < ppgtt->num_pd_entries; i++) { - dma_addr_t pt_addr; + for (i = 0; i < ppgtt->num_pd_entries; i++) { + dma_addr_t pt_addr; - pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], - 0, 4096, - PCI_DMA_BIDIRECTIONAL); + pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], 0, 4096, + PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, - pt_addr)) { - ret = -EIO; - goto err_pd_pin; + if (pci_dma_mapping_error(dev->pdev, pt_addr)) { + ret = -EIO; + goto err_pd_pin; - } - ppgtt->pt_dma_addr[i] = pt_addr; } + ppgtt->pt_dma_addr[i] = pt_addr; } ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; @@ -294,11 +289,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev) for (i = 0; i < ppgtt->num_pd_entries; i++) { dma_addr_t pt_addr; - if (dev_priv->mm.gtt->needs_dmar) - pt_addr = ppgtt->pt_dma_addr[i]; - else - pt_addr = page_to_phys(ppgtt->pt_pages[i]); - + pt_addr = ppgtt->pt_dma_addr[i]; pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); pd_entry |= GEN6_PDE_VALID; @@ -730,16 +721,12 @@ int i915_gem_gtt_init(struct drm_device *dev) return 0; } - dev_priv->mm.gtt = kzalloc(sizeof(*dev_priv->mm.gtt), GFP_KERNEL); - if (!dev_priv->mm.gtt) - return -ENOMEM; - if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); -#ifdef CONFIG_INTEL_IOMMU - dev_priv->mm.gtt->needs_dmar = 1; -#endif + dev_priv->mm.gtt = kzalloc(sizeof(*dev_priv->mm.gtt), GFP_KERNEL); + if (!dev_priv->mm.gtt) + return -ENOMEM; /* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */ gtt_bus_addr = pci_resource_start(dev->pdev, 0) + (2<<20); diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index c787ee4c4c07..984105cddc57 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -11,8 +11,6 @@ struct intel_gtt { /* Part of the gtt that is mappable by the cpu, for those chips where * this is not the full gtt. */ unsigned int gtt_mappable_entries; - /* Whether i915 needs to use the dmar apis or not. */ - unsigned int needs_dmar : 1; /* needed for ioremap in drm/i915 */ phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -- cgit 1.4.1 From e5c653777986b40e2986d2c918847fddbcba3a34 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:34 -0800 Subject: agp/intel: Add gma_bus_addr It is no longer used in the i915 code, so isolate it from the shared struct. This was originally part of: commit 0e275518f325418d559c05327775bff894b237f7 Author: Ben Widawsky Date: Mon Jan 14 13:35:33 2013 -0800 agp/intel: decouple more of the agp-i915 sharing Reviewed-by: Rodrigo Vivi Signed-off-by: Ben Widawsky That commit had some other hunks which can't be used due to issues Daniel found in previous commits. Signed-off-by: Ben Widawsky [danvet: drop squash notice from the commit since it's imo ok to keep this one separate.] Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 5 +++-- include/drm/intel-gtt.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index b45241479a56..ff5f3483e8ea 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -79,6 +79,7 @@ static struct _intel_private { int refcount; /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; + phys_addr_t gma_bus_addr; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -625,7 +626,7 @@ static int intel_gtt_init(void) pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &gma_addr); - intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); + intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); return 0; } @@ -781,7 +782,7 @@ static int intel_fake_agp_configure(void) return -EIO; intel_private.clear_fake_agp = true; - agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; + agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; return 0; } diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 984105cddc57..769b6c79097e 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -11,8 +11,6 @@ struct intel_gtt { /* Part of the gtt that is mappable by the cpu, for those chips where * this is not the full gtt. */ unsigned int gtt_mappable_entries; - /* needed for ioremap in drm/i915 */ - phys_addr_t gma_bus_addr; } *intel_gtt_get(void); int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, -- cgit 1.4.1 From a54c0c279f3864171fe53c66e769d5a137c5c651 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 Jan 2013 14:45:00 -0800 Subject: drm/i915: remove intel_gtt structure With the probe call in our dispatch table, we can now cut away the last three remaining members in the intel_gtt shared struct and so remove it completely. v2: Rebased on top of Daniel's series Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau [danvet: bikeshed commit message a bit.] Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 36 ++++++++++++++++++++-------------- drivers/gpu/drm/i915/i915_drv.h | 3 +-- drivers/gpu/drm/i915/i915_gem_gtt.c | 30 ++++++---------------------- drivers/gpu/drm/i915/i915_gem_stolen.c | 8 ++++---- include/drm/intel-gtt.h | 10 +--------- 5 files changed, 33 insertions(+), 54 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index ff5f3483e8ea..d8e7e6c9114e 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -60,7 +60,6 @@ struct intel_gtt_driver { }; static struct _intel_private { - struct intel_gtt base; const struct intel_gtt_driver *driver; struct pci_dev *pcidev; /* device one */ struct pci_dev *bridge_dev; @@ -80,6 +79,13 @@ static struct _intel_private { /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; phys_addr_t gma_bus_addr; + /* Size of memory reserved for graphics by the BIOS */ + unsigned int stolen_size; + /* Total number of gtt entries. */ + unsigned int gtt_total_entries; + /* Part of the gtt that is mappable by the cpu, for those chips where + * this is not the full gtt. */ + unsigned int gtt_mappable_entries; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -510,7 +516,7 @@ static unsigned int intel_gtt_total_entries(void) /* On previous hardware, the GTT size was just what was * required to map the aperture. */ - return intel_private.base.gtt_mappable_entries; + return intel_private.gtt_mappable_entries; } } @@ -576,8 +582,8 @@ static int intel_gtt_init(void) if (ret != 0) return ret; - intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); - intel_private.base.gtt_total_entries = intel_gtt_total_entries(); + intel_private.gtt_mappable_entries = intel_gtt_mappable_entries(); + intel_private.gtt_total_entries = intel_gtt_total_entries(); /* save the PGETBL reg for resume */ intel_private.PGETBL_save = @@ -589,10 +595,10 @@ static int intel_gtt_init(void) dev_info(&intel_private.bridge_dev->dev, "detected gtt size: %dK total, %dK mappable\n", - intel_private.base.gtt_total_entries * 4, - intel_private.base.gtt_mappable_entries * 4); + intel_private.gtt_total_entries * 4, + intel_private.gtt_mappable_entries * 4); - gtt_map_size = intel_private.base.gtt_total_entries * 4; + gtt_map_size = intel_private.gtt_total_entries * 4; intel_private.gtt = NULL; if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) @@ -609,7 +615,7 @@ static int intel_gtt_init(void) global_cache_flush(); /* FIXME: ? */ - intel_private.base.stolen_size = intel_gtt_stolen_size(); + intel_private.stolen_size = intel_gtt_stolen_size(); intel_private.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; @@ -637,8 +643,7 @@ static int intel_fake_agp_fetch_size(void) unsigned int aper_size; int i; - aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) - / MB(1); + aper_size = (intel_private.gtt_mappable_entries << PAGE_SHIFT) / MB(1); for (i = 0; i < num_sizes; i++) { if (aper_size == intel_fake_agp_sizes[i].size) { @@ -845,8 +850,8 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, int ret = -EINVAL; if (intel_private.clear_fake_agp) { - int start = intel_private.base.stolen_size / PAGE_SIZE; - int end = intel_private.base.gtt_mappable_entries; + int start = intel_private.stolen_size / PAGE_SIZE; + int end = intel_private.gtt_mappable_entries; intel_gtt_clear_range(start, end - start); intel_private.clear_fake_agp = false; } @@ -857,7 +862,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, if (mem->page_count == 0) goto out; - if (pg_start + mem->page_count > intel_private.base.gtt_total_entries) + if (pg_start + mem->page_count > intel_private.gtt_total_entries) goto out_err; if (type != mem->type) @@ -1366,9 +1371,10 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, } EXPORT_SYMBOL(intel_gmch_probe); -struct intel_gtt *intel_gtt_get(void) +void intel_gtt_get(size_t *gtt_total, size_t *stolen_size) { - return &intel_private.base; + *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT; + *stolen_size = intel_private.stolen_size; } EXPORT_SYMBOL(intel_gtt_get); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dee8d5c7a235..d3274164143d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -406,6 +406,7 @@ struct i915_gtt { unsigned int pg_start, enum i915_cache_level cache_level); }; +#define gtt_total_entries(gtt) ((gtt).total >> PAGE_SHIFT) #define I915_PPGTT_PD_ENTRIES 512 #define I915_PPGTT_PT_ENTRIES 1024 @@ -696,8 +697,6 @@ struct intel_l3_parity { }; struct i915_gem_mm { - /** Bridge to intel-gtt-ko */ - struct intel_gtt *gtt; /** Memory allocator for GTT stolen memory */ struct drm_mm stolen; /** Memory allocator for GTT */ diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 87249e8cd4a0..f7e0018626bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -182,7 +182,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 * entries. For aliasing ppgtt support we just steal them at the end for * now. */ - first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; + first_pd_entry_in_global_pt = + gtt_total_entries(dev_priv->gtt) - I915_PPGTT_PD_ENTRIES; ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; ppgtt->clear_range = gen6_ppgtt_clear_range; @@ -473,7 +474,7 @@ static void gen6_ggtt_clear_range(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; gtt_pte_t scratch_pte; gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; - const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; + const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; int i; if (WARN(num_entries > max_entries, @@ -634,7 +635,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev) unsigned long gtt_size, mappable_size; int ret; - gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT; + gtt_size = dev_priv->gtt.total; mappable_size = dev_priv->gtt.mappable_end; if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { @@ -778,7 +779,6 @@ void gen6_gmch_remove(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; iounmap(dev_priv->gtt.gsm); teardown_scratch_page(dev_priv->dev); - kfree(dev_priv->mm.gtt); } static int i915_gmch_probe(struct drm_device *dev, @@ -788,22 +788,13 @@ static int i915_gmch_probe(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; int ret; - /* This is a temporary hack to make the code cleaner in - * i915_gem_gtt_init. I promise it will go away very shortly. */ - kfree(dev_priv->mm.gtt); - ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); if (!ret) { DRM_ERROR("failed to set up gmch\n"); return -EIO; } - dev_priv->mm.gtt = intel_gtt_get(); - if (!dev_priv->mm.gtt) { - DRM_ERROR("Failed to initialize GTT\n"); - intel_gmch_remove(); - return -ENODEV; - } + intel_gtt_get(gtt_total, stolen); dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); dev_priv->gtt.gtt_clear_range = i915_ggtt_clear_range; @@ -824,10 +815,6 @@ int i915_gem_gtt_init(struct drm_device *dev) unsigned long gtt_size; int ret; - dev_priv->mm.gtt = kzalloc(sizeof(*dev_priv->mm.gtt), GFP_KERNEL); - if (!dev_priv->mm.gtt) - return -ENOMEM; - gtt->mappable_base = pci_resource_start(dev->pdev, 2); gtt->mappable_end = pci_resource_len(dev->pdev, 2); @@ -841,13 +828,8 @@ int i915_gem_gtt_init(struct drm_device *dev) ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total, &dev_priv->gtt.stolen_size); - if (ret) { - kfree(dev_priv->mm.gtt); + if (ret) return ret; - } - - dev_priv->mm.gtt->gtt_total_entries = dev_priv->gtt.total >> PAGE_SHIFT; - dev_priv->mm.gtt->stolen_size = dev_priv->gtt.stolen_size; gtt_size = (dev_priv->gtt.total >> PAGE_SHIFT) * sizeof(gtt_pte_t); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f21ae17e298f..69d97cbac13c 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -187,11 +187,11 @@ 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); + DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n", + dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base); /* Basic memrange allocator for stolen space */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->mm.gtt->stolen_size); + drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size); return 0; } @@ -205,7 +205,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, struct scatterlist *sg; DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size); - BUG_ON(offset > dev_priv->mm.gtt->stolen_size - size); + BUG_ON(offset > dev_priv->gtt.stolen_size - size); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 769b6c79097e..cf105557fea9 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -3,15 +3,7 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H -struct intel_gtt { - /* Size of memory reserved for graphics by the BIOS */ - unsigned int stolen_size; - /* Total number of gtt entries. */ - unsigned int gtt_total_entries; - /* Part of the gtt that is mappable by the cpu, for those chips where - * this is not the full gtt. */ - unsigned int gtt_mappable_entries; -} *intel_gtt_get(void); +void intel_gtt_get(size_t *gtt_total, size_t *stolen_size); int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, struct agp_bridge_data *bridge); -- cgit 1.4.1 From 41907ddc1b71aaa4ef5290f46f0ec49d581d6aac Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 8 Feb 2013 11:32:47 -0800 Subject: drm/i915: Fix gen2 mappable calculations When I refactored the code initially, I forgot that gen2 uses a different bar for the CPU mappable aperture. The agp-less code knows nothing of generations less than 5, so we have to expand the gtt_probe function to include the mappable base and end. It was originally broken by me: commit baa09f5fd8a6d033ec075355dda99a65b7f6a0f3 Author: Ben Widawsky Date: Thu Jan 24 13:49:57 2013 -0800 drm/i915: Add probe and remove to the gtt ops Reported-by: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 5 ++++- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem_gtt.c | 23 ++++++++++++++--------- include/drm/intel-gtt.h | 3 ++- 4 files changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index d8e7e6c9114e..207e5c36e9ec 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1371,10 +1371,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, } EXPORT_SYMBOL(intel_gmch_probe); -void intel_gtt_get(size_t *gtt_total, size_t *stolen_size) +void intel_gtt_get(size_t *gtt_total, size_t *stolen_size, + phys_addr_t *mappable_base, unsigned long *mappable_end) { *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT; *stolen_size = intel_private.stolen_size; + *mappable_base = intel_private.gma_bus_addr; + *mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT; } EXPORT_SYMBOL(intel_gtt_get); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a7860ea21af9..0f1d15bac517 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -399,7 +399,8 @@ struct i915_gtt { /* global gtt ops */ int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total, - size_t *stolen); + size_t *stolen, phys_addr_t *mappable_base, + unsigned long *mappable_end); void (*gtt_remove)(struct drm_device *dev); void (*gtt_clear_range)(struct drm_device *dev, unsigned int first_entry, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index bdaca3f47988..926a1e2dd234 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -725,7 +725,9 @@ static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl) static int gen6_gmch_probe(struct drm_device *dev, size_t *gtt_total, - size_t *stolen) + size_t *stolen, + phys_addr_t *mappable_base, + unsigned long *mappable_end) { struct drm_i915_private *dev_priv = dev->dev_private; phys_addr_t gtt_bus_addr; @@ -733,11 +735,13 @@ static int gen6_gmch_probe(struct drm_device *dev, u16 snb_gmch_ctl; int ret; + *mappable_base = pci_resource_start(dev->pdev, 2); + *mappable_end = pci_resource_len(dev->pdev, 2); + /* 64/512MB is the current min/max we actually know of, but this is just * a coarse sanity check. */ - if ((dev_priv->gtt.mappable_end < (64<<20) || - (dev_priv->gtt.mappable_end > (512<<20)))) { + if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { DRM_ERROR("Unknown GMADR size (%lx)\n", dev_priv->gtt.mappable_end); return -ENXIO; @@ -782,7 +786,9 @@ static void gen6_gmch_remove(struct drm_device *dev) static int i915_gmch_probe(struct drm_device *dev, size_t *gtt_total, - size_t *stolen) + size_t *stolen, + phys_addr_t *mappable_base, + unsigned long *mappable_end) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -793,7 +799,7 @@ static int i915_gmch_probe(struct drm_device *dev, return -EIO; } - intel_gtt_get(gtt_total, stolen); + intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); dev_priv->gtt.gtt_clear_range = i915_ggtt_clear_range; @@ -814,9 +820,6 @@ int i915_gem_gtt_init(struct drm_device *dev) unsigned long gtt_size; int ret; - gtt->mappable_base = pci_resource_start(dev->pdev, 2); - gtt->mappable_end = pci_resource_len(dev->pdev, 2); - if (INTEL_INFO(dev)->gen <= 5) { dev_priv->gtt.gtt_probe = i915_gmch_probe; dev_priv->gtt.gtt_remove = i915_gmch_remove; @@ -826,7 +829,9 @@ int i915_gem_gtt_init(struct drm_device *dev) } ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total, - &dev_priv->gtt.stolen_size); + &dev_priv->gtt.stolen_size, + >t->mappable_base, + >t->mappable_end); if (ret) return ret; diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index cf105557fea9..b08bdade6002 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -3,7 +3,8 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H -void intel_gtt_get(size_t *gtt_total, size_t *stolen_size); +void intel_gtt_get(size_t *gtt_total, size_t *stolen_size, + phys_addr_t *mappable_base, unsigned long *mappable_end); int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, struct agp_bridge_data *bridge); -- cgit 1.4.1 From da88a5f7f7d434e2cde1b3e19d952e6d84533662 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Feb 2013 09:31:53 +0000 Subject: drm/i915: Disable WC PTE updates to w/a buggy IOMMU on ILK Whilst IOMMU is enabled for the Intel GPU on Ironlake, it appears that using WC writes to update the PTE on the GPU fails miserably. The result looks like the majority of the writes do not land leading to lots of screen corruption and a hard system hang. v2: s/ Bugzilla: https://bugzilla.freedesktop.org/show_bug.cgi?id=60391 Signed-off-by: Chris Wilson Tested-by: Nathan Myers [danvet: Remove cc: stable and add tested-by.] Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-gtt.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 207e5c36e9ec..b8e2014cb9cb 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -572,6 +572,40 @@ static void intel_gtt_cleanup(void) intel_gtt_teardown_scratch_page(); } +/* Certain Gen5 chipsets require require idling the GPU before + * unmapping anything from the GTT when VT-d is enabled. + */ +static inline int needs_ilk_vtd_wa(void) +{ +#ifdef CONFIG_INTEL_IOMMU + const unsigned short gpu_devid = intel_private.pcidev->device; + + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. + */ + if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || + gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && + intel_iommu_gfx_mapped) + return 1; +#endif + return 0; +} + +static bool intel_gtt_can_wc(void) +{ + if (INTEL_GTT_GEN <= 2) + return false; + + if (INTEL_GTT_GEN >= 6) + return false; + + /* Reports of major corruption with ILK vt'd enabled */ + if (needs_ilk_vtd_wa()) + return false; + + return true; +} + static int intel_gtt_init(void) { u32 gma_addr; @@ -601,7 +635,7 @@ static int intel_gtt_init(void) gtt_map_size = intel_private.gtt_total_entries * 4; intel_private.gtt = NULL; - if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) + if (intel_gtt_can_wc()) intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, gtt_map_size); if (intel_private.gtt == NULL) @@ -1072,7 +1106,6 @@ static void i965_write_entry(dma_addr_t addr, writel(addr | pte_flags, intel_private.gtt + entry); } - static int i9xx_setup(void) { u32 reg_addr, gtt_addr; -- cgit 1.4.1