diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 117 |
1 files changed, 80 insertions, 37 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a275cf6..405c827 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -32,6 +32,7 @@ #include <drm/radeon_drm.h> #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> +#include <linux/efi.h> #include "radeon_reg.h" #include "radeon.h" #include "atom.h" @@ -303,6 +304,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) + mc->real_vram_size = radeon_vram_limit; dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); @@ -351,6 +354,9 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; + if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + return false; + /* first check CRTCs */ if (ASIC_IS_DCE4(rdev)) { reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | @@ -712,19 +718,26 @@ int radeon_device_init(struct radeon_device *rdev, /* mutex initialization are all done here so we * can recall function without having locking issues */ - mutex_init(&rdev->cs_mutex); - mutex_init(&rdev->ib_pool.mutex); - mutex_init(&rdev->cp.mutex); + radeon_mutex_init(&rdev->cs_mutex); + radeon_mutex_init(&rdev->ib_pool.mutex); + for (i = 0; i < RADEON_NUM_RINGS; ++i) + mutex_init(&rdev->ring[i].mutex); mutex_init(&rdev->dc_hw_i2c_mutex); if (rdev->family >= CHIP_R600) spin_lock_init(&rdev->ih.lock); mutex_init(&rdev->gem.mutex); mutex_init(&rdev->pm.mutex); mutex_init(&rdev->vram_mutex); - rwlock_init(&rdev->fence_drv.lock); + rwlock_init(&rdev->fence_lock); + rwlock_init(&rdev->semaphore_drv.lock); INIT_LIST_HEAD(&rdev->gem.objects); init_waitqueue_head(&rdev->irq.vblank_queue); init_waitqueue_head(&rdev->irq.idle_queue); + INIT_LIST_HEAD(&rdev->semaphore_drv.bo); + /* initialize vm here */ + rdev->vm_manager.use_bitmap = 1; + rdev->vm_manager.max_pfn = 1 << 20; + INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); /* Set asic functions */ r = radeon_asic_init(rdev); @@ -746,22 +759,29 @@ int radeon_device_init(struct radeon_device *rdev, /* set DMA mask + need_dma32 flags. * PCIE - can handle 40-bits. - * IGP - can handle 40-bits (in theory) + * IGP - can handle 40-bits * AGP - generally dma32 is safest - * PCI - only dma32 + * PCI - dma32 for legacy pci gart, 40 bits on newer asics */ rdev->need_dma32 = false; if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; - if (rdev->flags & RADEON_IS_PCI) + if ((rdev->flags & RADEON_IS_PCI) && + (rdev->family < CHIP_RS400)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { rdev->need_dma32 = true; + dma_bits = 32; printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } + r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); + printk(KERN_WARNING "radeon: No coherent DMA available.\n"); + } /* Registers mapping */ /* TODO: block userspace mapping of io register */ @@ -809,15 +829,20 @@ int radeon_device_init(struct radeon_device *rdev, if (r) return r; } - if (radeon_testing) { + if ((radeon_testing & 1)) { radeon_test_moves(rdev); } + if ((radeon_testing & 2)) { + radeon_test_syncing(rdev); + } if (radeon_benchmarking) { - radeon_benchmark(rdev); + radeon_benchmark(rdev, radeon_benchmarking); } return 0; } +static void radeon_debugfs_remove_files(struct radeon_device *rdev); + void radeon_device_fini(struct radeon_device *rdev) { DRM_INFO("radeon: finishing device.\n"); @@ -832,6 +857,7 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->rio_mem = NULL; iounmap(rdev->rmmio); rdev->rmmio = NULL; + radeon_debugfs_remove_files(rdev); } @@ -843,7 +869,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) struct radeon_device *rdev; struct drm_crtc *crtc; struct drm_connector *connector; - int r; + int i, r; if (dev == NULL || dev->dev_private == NULL) { return -ENODEV; @@ -884,7 +910,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) /* evict vram memory */ radeon_bo_evict_vram(rdev); /* wait for gpu to finish processing current batch */ - radeon_fence_wait_last(rdev); + for (i = 0; i < RADEON_NUM_RINGS; i++) + radeon_fence_wait_last(rdev, i); radeon_save_bios_scratch_regs(rdev); @@ -933,9 +960,11 @@ int radeon_resume_kms(struct drm_device *dev) radeon_fbdev_set_suspend(rdev, 0); console_unlock(); - /* init dig PHYs */ - if (rdev->is_atom_bios) + /* init dig PHYs, disp eng pll */ + if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); + radeon_atom_dcpll_init(rdev); + } /* reset hpd state */ radeon_hpd_init(rdev); /* blat the mode back in */ @@ -954,6 +983,9 @@ int radeon_gpu_reset(struct radeon_device *rdev) int r; int resched; + /* Prevent CS ioctl from interfering */ + radeon_mutex_lock(&rdev->cs_mutex); + radeon_save_bios_scratch_regs(rdev); /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); @@ -966,10 +998,15 @@ int radeon_gpu_reset(struct radeon_device *rdev) radeon_restore_bios_scratch_regs(rdev); drm_helper_resume_force_mode(rdev->ddev); ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - return 0; } - /* bad news, how to tell it to userspace ? */ - dev_info(rdev->dev, "GPU reset failed\n"); + + radeon_mutex_unlock(&rdev->cs_mutex); + + if (r) { + /* bad news, how to tell it to userspace ? */ + dev_info(rdev->dev, "GPU reset failed\n"); + } + return r; } @@ -977,33 +1014,29 @@ int radeon_gpu_reset(struct radeon_device *rdev) /* * Debugfs */ -struct radeon_debugfs { - struct drm_info_list *files; - unsigned num_files; -}; -static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES]; -static unsigned _radeon_debugfs_count = 0; - int radeon_debugfs_add_files(struct radeon_device *rdev, struct drm_info_list *files, unsigned nfiles) { unsigned i; - for (i = 0; i < _radeon_debugfs_count; i++) { - if (_radeon_debugfs[i].files == files) { + for (i = 0; i < rdev->debugfs_count; i++) { + if (rdev->debugfs[i].files == files) { /* Already registered */ return 0; } } - if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) { - DRM_ERROR("Reached maximum number of debugfs files.\n"); - DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n"); + + i = rdev->debugfs_count + 1; + if (i > RADEON_DEBUGFS_MAX_COMPONENTS) { + DRM_ERROR("Reached maximum number of debugfs components.\n"); + DRM_ERROR("Report so we increase " + "RADEON_DEBUGFS_MAX_COMPONENTS.\n"); return -EINVAL; } - _radeon_debugfs[_radeon_debugfs_count].files = files; - _radeon_debugfs[_radeon_debugfs_count].num_files = nfiles; - _radeon_debugfs_count++; + rdev->debugfs[rdev->debugfs_count].files = files; + rdev->debugfs[rdev->debugfs_count].num_files = nfiles; + rdev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) drm_debugfs_create_files(files, nfiles, rdev->ddev->control->debugfs_root, @@ -1015,6 +1048,22 @@ int radeon_debugfs_add_files(struct radeon_device *rdev, return 0; } +static void radeon_debugfs_remove_files(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + unsigned i; + + for (i = 0; i < rdev->debugfs_count; i++) { + drm_debugfs_remove_files(rdev->debugfs[i].files, + rdev->debugfs[i].num_files, + rdev->ddev->control); + drm_debugfs_remove_files(rdev->debugfs[i].files, + rdev->debugfs[i].num_files, + rdev->ddev->primary); + } +#endif +} + #if defined(CONFIG_DEBUG_FS) int radeon_debugfs_init(struct drm_minor *minor) { @@ -1023,11 +1072,5 @@ int radeon_debugfs_init(struct drm_minor *minor) void radeon_debugfs_cleanup(struct drm_minor *minor) { - unsigned i; - - for (i = 0; i < _radeon_debugfs_count; i++) { - drm_debugfs_remove_files(_radeon_debugfs[i].files, - _radeon_debugfs[i].num_files, minor); - } } #endif |