From 3f50b0222e4c6ac59a5c4819f8be0fa500970381 Mon Sep 17 00:00:00 2001 From: Kevin Winchester Date: Tue, 17 Nov 2009 14:38:45 -0800 Subject: agp: correct missing cleanup on error in agp_add_bridge While investigating a kmemleak detected leak, I encountered the agp_add_bridge function. It appears to be responsible for freeing the agp_bridge_data in the case of a failure, but it is only doing so for some errors. Fix it to always free the bridge data if a failure condition is encountered. Signed-off-by: Kevin Winchester Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/agp/backend.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/char/agp') diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index a56ca080e10..c3ab46da51a 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -285,18 +285,22 @@ int agp_add_bridge(struct agp_bridge_data *bridge) { int error; - if (agp_off) - return -ENODEV; + if (agp_off) { + error = -ENODEV; + goto err_put_bridge; + } if (!bridge->dev) { printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } /* Grab reference on the chipset driver. */ if (!try_module_get(bridge->driver->owner)) { dev_info(&bridge->dev->dev, "can't lock chipset driver\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } error = agp_backend_initialize(bridge); @@ -326,6 +330,7 @@ frontend_err: agp_backend_cleanup(bridge); err_out: module_put(bridge->driver->owner); +err_put_bridge: agp_put_bridge(bridge); return error; } -- cgit v1.2.3-70-g09d2 From 67fe63b0715ccfaefa0af8a6e705c5470ee5cada Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 7 Jan 2010 12:58:51 -0700 Subject: agp/hp: fixup hp agp after ACPI changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 15b8dd53f5ffa changed the string in info->hardware_id from a static array to a pointer and added a length field. But instead of changing "sizeof(array)" to "length", we changed it to "sizeof(length)" (== 4), which corrupts the string we're trying to null-terminate. We no longer even need to null-terminate the string, but we *do* need to check whether we found a HID. If there's no HID, we used to have an empty array, but now we have a null pointer. The combination of these defects causes this oops: Unable to handle kernel NULL pointer dereference (address 0000000000000003) modprobe[895]: Oops 8804682956800 [1] ip is at zx1_gart_probe+0xd0/0xcc0 [hp_agp] http://marc.info/?l=linux-ia64&m=126264484923647&w=2 Signed-off-by: Bjorn Helgaas Reported-by: Émeric Maschino Signed-off-by: Dave Airlie --- drivers/char/agp/hp-agp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char/agp') diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 9047b271465..dc8a6f70483 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -488,9 +488,8 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = obj; do { status = acpi_get_object_info(handle, &info); - if (ACPI_SUCCESS(status)) { + if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) { /* TBD check _CID also */ - info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; match = (strcmp(info->hardware_id.string, "HWP0001") == 0); kfree(info); if (match) { -- cgit v1.2.3-70-g09d2 From 3d4a7882b11299104a0e74425dece2e26ac98024 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 7 Jan 2010 12:58:56 -0700 Subject: agp/hp: fail gracefully if we don't find an IOC Bail out if we don't find an enclosing IOC. Previously, if we didn't find one, we tried to set things up using garbage for the SBA/IOC register address, which causes a crash. This crash only happens if firmware supplies a defective ACPI namespace, so it doesn't fix any problems in the field. Signed-off-by: Bjorn Helgaas Signed-off-by: Dave Airlie --- drivers/char/agp/hp-agp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/char/agp') diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index dc8a6f70483..58752b70efe 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -508,6 +508,9 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = parent; } while (ACPI_SUCCESS(status)); + if (ACPI_FAILURE(status)) + return AE_OK; /* found no enclosing IOC */ + if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; -- cgit v1.2.3-70-g09d2 From 42590a75019a50012f25a962246498dead428433 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 4 Jan 2010 16:16:23 +0900 Subject: x86/agp: Fix agp_amd64_init and agp_amd64_cleanup This fixes the regression introduced by the commit f405d2c02395a74d3883bd03ded36457aa3697ad. The above commit fixes the following issue: http://marc.info/?l=linux-kernel&m=126192729110083&w=2 However, it doesn't work properly when you remove and insert the agp_amd64 module again. agp_amd64_init() and agp_amd64_cleanup should be called only when gart_iommu is not called earlier (that is, the GART IOMMU is not enabled). We need to use 'gart_iommu_aperture' to see if GART IOMMU is enabled or not. Signed-off-by: FUJITA Tomonori Cc: mitov@issp.bas.bg Cc: davej@redhat.com LKML-Reference: <20100104161603L.fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Ingo Molnar --- arch/x86/kernel/aperture_64.c | 1 + drivers/char/agp/amd64-agp.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/char/agp') diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 3704997e8b2..f147a95fd84 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -31,6 +31,7 @@ #include int gart_iommu_aperture; +EXPORT_SYMBOL_GPL(gart_iommu_aperture); int gart_iommu_aperture_disabled __initdata; int gart_iommu_aperture_allowed __initdata; diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 5aa7a586a7f..1afb8968a34 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,12 +725,11 @@ static struct pci_driver agp_amd64_pci_driver = { int __init agp_amd64_init(void) { int err = 0; - static int done = 0; if (agp_off) return -EINVAL; - if (done++) + if (gart_iommu_aperture) return agp_bridges_found ? 0 : -ENODEV; err = pci_register_driver(&agp_amd64_pci_driver); @@ -771,6 +770,8 @@ int __init agp_amd64_init(void) static void __exit agp_amd64_cleanup(void) { + if (gart_iommu_aperture) + return; if (aperture_resource) release_resource(aperture_resource); pci_unregister_driver(&agp_amd64_pci_driver); -- cgit v1.2.3-70-g09d2 From 9b974cc17166d31afed2638d56bdbf9829afbfaa Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:06 +0800 Subject: drm/i915: enable 36bit physical address for hardware status page This enables possible 36bit address mask on 965G that use physical address for hw status page. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/char/agp/intel-agp.c | 6 +++++- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/char/agp') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 30c36ac2cd0..3999a5f25f3 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -2460,10 +2460,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, &bridge->mode); } - if (bridge->driver->mask_memory == intel_i965_mask_memory) + if (bridge->driver->mask_memory == intel_i965_mask_memory) { if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) dev_err(&intel_private.pcidev->dev, "set gfx device dma mask 36bit failed!\n"); + else + pci_set_consistent_dma_mask(intel_private.pcidev, + DMA_BIT_MASK(36)); + } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bbe47812e4b..e660ac07f3b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -134,6 +134,10 @@ static int i915_init_phys_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + if (IS_I965G(dev)) + dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & + 0xf0; + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; -- cgit v1.2.3-70-g09d2