Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: vmwgfx: Fix fb VRAM pinning failure due to fragmentation vmwgfx: Remove initialisation of dev::devname vmwgfx: Enable use of the vblank system vmwgfx: vt-switch (master drop) fixes drm/vmwgfx: Fix breakage introduced by commit "drm: block userspace under allocating buffer and having drivers overwrite it (v2)" drm: Hold the mutex when dropping the last GEM reference (v2) drm/gem: handlecount isn't really a kref so don't make it one. drm: i810/i830: fix locked ioctl variant drm/radeon/kms: add quirk for MSI K9A2GM motherboard drm/radeon/kms: fix potential segfault in r600_ioctl_wait_idle drm: Prune GEM vma entries drm/radeon/kms: fix up encoder info messages for DFP6 drm/radeon: fix PCI ID 5657 to be an RV410
This commit is contained in:
commit
18ffe4b18c
@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev,
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&obj->refcount);
|
||||
kref_init(&obj->handlecount);
|
||||
atomic_set(&obj->handle_count, 0);
|
||||
obj->size = size;
|
||||
|
||||
atomic_inc(&dev->object_count);
|
||||
@ -462,28 +462,6 @@ drm_gem_object_free(struct kref *kref)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_free);
|
||||
|
||||
/**
|
||||
* Called after the last reference to the object has been lost.
|
||||
* Must be called without holding struct_mutex
|
||||
*
|
||||
* Frees the object
|
||||
*/
|
||||
void
|
||||
drm_gem_object_free_unlocked(struct kref *kref)
|
||||
{
|
||||
struct drm_gem_object *obj = (struct drm_gem_object *) kref;
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
if (dev->driver->gem_free_object_unlocked != NULL)
|
||||
dev->driver->gem_free_object_unlocked(obj);
|
||||
else if (dev->driver->gem_free_object != NULL) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
dev->driver->gem_free_object(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_free_unlocked);
|
||||
|
||||
static void drm_gem_object_ref_bug(struct kref *list_kref)
|
||||
{
|
||||
BUG();
|
||||
@ -496,12 +474,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref)
|
||||
* called before drm_gem_object_free or we'll be touching
|
||||
* freed memory
|
||||
*/
|
||||
void
|
||||
drm_gem_object_handle_free(struct kref *kref)
|
||||
void drm_gem_object_handle_free(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_gem_object *obj = container_of(kref,
|
||||
struct drm_gem_object,
|
||||
handlecount);
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
/* Remove any name for this object */
|
||||
@ -528,6 +502,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
|
||||
drm_gem_object_reference(obj);
|
||||
|
||||
mutex_lock(&obj->dev->struct_mutex);
|
||||
drm_vm_open_locked(vma);
|
||||
mutex_unlock(&obj->dev->struct_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_vm_open);
|
||||
|
||||
@ -535,7 +513,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
mutex_lock(&obj->dev->struct_mutex);
|
||||
drm_vm_close_locked(vma);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&obj->dev->struct_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_vm_close);
|
||||
|
||||
|
@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data)
|
||||
|
||||
seq_printf(m, "%6d %8zd %7d %8d\n",
|
||||
obj->name, obj->size,
|
||||
atomic_read(&obj->handlecount.refcount),
|
||||
atomic_read(&obj->handle_count),
|
||||
atomic_read(&obj->refcount.refcount));
|
||||
return 0;
|
||||
}
|
||||
|
@ -433,6 +433,25 @@ static void drm_vm_open(struct vm_area_struct *vma)
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
void drm_vm_close_locked(struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_file *priv = vma->vm_file->private_data;
|
||||
struct drm_device *dev = priv->minor->dev;
|
||||
struct drm_vma_entry *pt, *temp;
|
||||
|
||||
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
||||
vma->vm_start, vma->vm_end - vma->vm_start);
|
||||
atomic_dec(&dev->vma_count);
|
||||
|
||||
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
|
||||
if (pt->vma == vma) {
|
||||
list_del(&pt->head);
|
||||
kfree(pt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \c close method for all virtual memory types.
|
||||
*
|
||||
@ -445,20 +464,9 @@ static void drm_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_file *priv = vma->vm_file->private_data;
|
||||
struct drm_device *dev = priv->minor->dev;
|
||||
struct drm_vma_entry *pt, *temp;
|
||||
|
||||
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
||||
vma->vm_start, vma->vm_end - vma->vm_start);
|
||||
atomic_dec(&dev->vma_count);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
|
||||
if (pt->vma == vma) {
|
||||
list_del(&pt->head);
|
||||
kfree(pt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_vm_close_locked(vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
|
||||
static const struct file_operations i810_buffer_fops = {
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.unlocked_ioctl = i810_ioctl,
|
||||
.mmap = i810_mmap_buffers,
|
||||
.fasync = drm_fasync,
|
||||
};
|
||||
|
@ -118,7 +118,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
|
||||
static const struct file_operations i830_buffer_fops = {
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.unlocked_ioctl = i830_ioctl,
|
||||
.mmap = i830_mmap_buffers,
|
||||
.fasync = drm_fasync,
|
||||
};
|
||||
|
@ -136,14 +136,12 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_gem_handle_create(file_priv, obj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
if (ret) {
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sink the floating reference from kref_init(handlecount) */
|
||||
drm_gem_object_handle_unreference_unlocked(obj);
|
||||
|
||||
args->handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev,
|
||||
drm_fb_helper_fini(&ifbdev->helper);
|
||||
|
||||
drm_framebuffer_cleanup(&ifb->base);
|
||||
if (ifb->obj)
|
||||
if (ifb->obj) {
|
||||
drm_gem_object_handle_unreference(ifb->obj);
|
||||
drm_gem_object_unreference(ifb->obj);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -352,6 +352,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
|
||||
|
||||
if (nouveau_fb->nvbo) {
|
||||
nouveau_bo_unmap(nouveau_fb->nvbo);
|
||||
drm_gem_object_handle_unreference_unlocked(nouveau_fb->nvbo->gem);
|
||||
drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
|
||||
nouveau_fb->nvbo = NULL;
|
||||
}
|
||||
|
@ -167,11 +167,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
|
||||
ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_unreference_unlocked(nvbo->gem);
|
||||
out:
|
||||
drm_gem_object_handle_unreference_unlocked(nvbo->gem);
|
||||
|
||||
if (ret)
|
||||
drm_gem_object_unreference_unlocked(nvbo->gem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
nouveau_bo_unpin(chan->notifier_bo);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_gem_object_handle_unreference_unlocked(chan->notifier_bo->gem);
|
||||
drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
|
||||
drm_mm_takedown(&chan->notifier_heap);
|
||||
}
|
||||
|
@ -3528,7 +3528,8 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
|
||||
/* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
|
||||
* rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
|
||||
*/
|
||||
if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
|
||||
if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
|
||||
rdev->vram_scratch.ptr) {
|
||||
void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
|
||||
u32 tmp;
|
||||
|
||||
|
@ -317,6 +317,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
|
||||
*connector_type = DRM_MODE_CONNECTOR_DVID;
|
||||
}
|
||||
|
||||
/* MSI K9A2GM V2/V3 board has no HDMI or DVI */
|
||||
if ((dev->pdev->device == 0x796e) &&
|
||||
(dev->pdev->subsystem_vendor == 0x1462) &&
|
||||
(dev->pdev->subsystem_device == 0x7302)) {
|
||||
if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
|
||||
(supported_device == ATOM_DEVICE_DFP3_SUPPORT))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
|
||||
if ((dev->pdev->device == 0x7941) &&
|
||||
(dev->pdev->subsystem_vendor == 0x147b) &&
|
||||
|
@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev)
|
||||
DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
|
||||
if (devices & ATOM_DEVICE_DFP5_SUPPORT)
|
||||
DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
|
||||
if (devices & ATOM_DEVICE_DFP6_SUPPORT)
|
||||
DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]);
|
||||
if (devices & ATOM_DEVICE_TV1_SUPPORT)
|
||||
DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
|
||||
if (devices & ATOM_DEVICE_CV_SUPPORT)
|
||||
@ -841,8 +843,9 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
|
||||
|
||||
if (radeon_fb->obj)
|
||||
if (radeon_fb->obj) {
|
||||
drm_gem_object_unreference_unlocked(radeon_fb->obj);
|
||||
}
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(radeon_fb);
|
||||
}
|
||||
|
@ -94,8 +94,10 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
|
||||
ret = radeon_bo_reserve(rbo, false);
|
||||
if (likely(ret == 0)) {
|
||||
radeon_bo_kunmap(rbo);
|
||||
radeon_bo_unpin(rbo);
|
||||
radeon_bo_unreserve(rbo);
|
||||
}
|
||||
drm_gem_object_handle_unreference(gobj);
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
}
|
||||
|
||||
@ -325,8 +327,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct radeon_framebuffer *rfb = &rfbdev->rfb;
|
||||
struct radeon_bo *rbo;
|
||||
int r;
|
||||
|
||||
if (rfbdev->helper.fbdev) {
|
||||
info = rfbdev->helper.fbdev;
|
||||
@ -338,14 +338,8 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
|
||||
}
|
||||
|
||||
if (rfb->obj) {
|
||||
rbo = rfb->obj->driver_private;
|
||||
r = radeon_bo_reserve(rbo, false);
|
||||
if (likely(r == 0)) {
|
||||
radeon_bo_kunmap(rbo);
|
||||
radeon_bo_unpin(rbo);
|
||||
radeon_bo_unreserve(rbo);
|
||||
}
|
||||
drm_gem_object_unreference_unlocked(rfb->obj);
|
||||
radeonfb_destroy_pinned_object(rfb->obj);
|
||||
rfb->obj = NULL;
|
||||
}
|
||||
drm_fb_helper_fini(&rfbdev->helper);
|
||||
drm_framebuffer_cleanup(&rfb->base);
|
||||
|
@ -201,11 +201,11 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
return r;
|
||||
}
|
||||
r = drm_gem_handle_create(filp, gobj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
if (r) {
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
return r;
|
||||
}
|
||||
drm_gem_object_handle_unreference_unlocked(gobj);
|
||||
args->handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,13 +148,16 @@ static struct pci_device_id vmw_pci_id_list[] = {
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static char *vmw_devname = "vmwgfx";
|
||||
static int enable_fbdev;
|
||||
|
||||
static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
|
||||
static void vmw_master_init(struct vmw_master *);
|
||||
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *ptr);
|
||||
|
||||
MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
|
||||
module_param_named(enable_fbdev, enable_fbdev, int, 0600);
|
||||
|
||||
static void vmw_print_capabilities(uint32_t capabilities)
|
||||
{
|
||||
DRM_INFO("Capabilities:\n");
|
||||
@ -192,8 +195,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
vmw_kms_save_vga(dev_priv);
|
||||
|
||||
ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Unable to initialize FIFO.\n");
|
||||
@ -206,9 +207,35 @@ static int vmw_request_device(struct vmw_private *dev_priv)
|
||||
static void vmw_release_device(struct vmw_private *dev_priv)
|
||||
{
|
||||
vmw_fifo_release(dev_priv, &dev_priv->fifo);
|
||||
vmw_kms_restore_vga(dev_priv);
|
||||
}
|
||||
|
||||
int vmw_3d_resource_inc(struct vmw_private *dev_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev_priv->release_mutex);
|
||||
if (unlikely(dev_priv->num_3d_resources++ == 0)) {
|
||||
ret = vmw_request_device(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
--dev_priv->num_3d_resources;
|
||||
}
|
||||
mutex_unlock(&dev_priv->release_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void vmw_3d_resource_dec(struct vmw_private *dev_priv)
|
||||
{
|
||||
int32_t n3d;
|
||||
|
||||
mutex_lock(&dev_priv->release_mutex);
|
||||
if (unlikely(--dev_priv->num_3d_resources == 0))
|
||||
vmw_release_device(dev_priv);
|
||||
n3d = (int32_t) dev_priv->num_3d_resources;
|
||||
mutex_unlock(&dev_priv->release_mutex);
|
||||
|
||||
BUG_ON(n3d < 0);
|
||||
}
|
||||
|
||||
static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
{
|
||||
@ -228,6 +255,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
dev_priv->last_read_sequence = (uint32_t) -100;
|
||||
mutex_init(&dev_priv->hw_mutex);
|
||||
mutex_init(&dev_priv->cmdbuf_mutex);
|
||||
mutex_init(&dev_priv->release_mutex);
|
||||
rwlock_init(&dev_priv->resource_lock);
|
||||
idr_init(&dev_priv->context_idr);
|
||||
idr_init(&dev_priv->surface_idr);
|
||||
@ -244,6 +272,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
|
||||
dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
|
||||
|
||||
dev_priv->enable_fb = enable_fbdev;
|
||||
|
||||
mutex_lock(&dev_priv->hw_mutex);
|
||||
|
||||
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
|
||||
@ -343,17 +373,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
|
||||
dev->dev_private = dev_priv;
|
||||
|
||||
if (!dev->devname)
|
||||
dev->devname = vmw_devname;
|
||||
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
|
||||
ret = drm_irq_install(dev);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed installing irq: %d\n", ret);
|
||||
goto out_no_irq;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pci_request_regions(dev->pdev, "vmwgfx probe");
|
||||
dev_priv->stealth = (ret != 0);
|
||||
if (dev_priv->stealth) {
|
||||
@ -369,26 +388,52 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
goto out_no_device;
|
||||
}
|
||||
}
|
||||
ret = vmw_request_device(dev_priv);
|
||||
ret = vmw_kms_init(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_device;
|
||||
vmw_kms_init(dev_priv);
|
||||
goto out_no_kms;
|
||||
vmw_overlay_init(dev_priv);
|
||||
vmw_fb_init(dev_priv);
|
||||
if (dev_priv->enable_fb) {
|
||||
ret = vmw_3d_resource_inc(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_fifo;
|
||||
vmw_kms_save_vga(dev_priv);
|
||||
vmw_fb_init(dev_priv);
|
||||
DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
|
||||
"Detected device 3D availability.\n" :
|
||||
"Detected no device 3D availability.\n");
|
||||
} else {
|
||||
DRM_INFO("Delayed 3D detection since we're not "
|
||||
"running the device in SVGA mode yet.\n");
|
||||
}
|
||||
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
|
||||
ret = drm_irq_install(dev);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed installing irq: %d\n", ret);
|
||||
goto out_no_irq;
|
||||
}
|
||||
}
|
||||
|
||||
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
|
||||
register_pm_notifier(&dev_priv->pm_nb);
|
||||
|
||||
DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_device:
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
|
||||
drm_irq_uninstall(dev_priv->dev);
|
||||
if (dev->devname == vmw_devname)
|
||||
dev->devname = NULL;
|
||||
out_no_irq:
|
||||
if (dev_priv->enable_fb) {
|
||||
vmw_fb_close(dev_priv);
|
||||
vmw_kms_restore_vga(dev_priv);
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
out_no_fifo:
|
||||
vmw_overlay_close(dev_priv);
|
||||
vmw_kms_close(dev_priv);
|
||||
out_no_kms:
|
||||
if (dev_priv->stealth)
|
||||
pci_release_region(dev->pdev, 2);
|
||||
else
|
||||
pci_release_regions(dev->pdev);
|
||||
out_no_device:
|
||||
ttm_object_device_release(&dev_priv->tdev);
|
||||
out_err4:
|
||||
iounmap(dev_priv->mmio_virt);
|
||||
@ -415,19 +460,20 @@ static int vmw_driver_unload(struct drm_device *dev)
|
||||
|
||||
unregister_pm_notifier(&dev_priv->pm_nb);
|
||||
|
||||
vmw_fb_close(dev_priv);
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
|
||||
drm_irq_uninstall(dev_priv->dev);
|
||||
if (dev_priv->enable_fb) {
|
||||
vmw_fb_close(dev_priv);
|
||||
vmw_kms_restore_vga(dev_priv);
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
vmw_kms_close(dev_priv);
|
||||
vmw_overlay_close(dev_priv);
|
||||
vmw_release_device(dev_priv);
|
||||
if (dev_priv->stealth)
|
||||
pci_release_region(dev->pdev, 2);
|
||||
else
|
||||
pci_release_regions(dev->pdev);
|
||||
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
|
||||
drm_irq_uninstall(dev_priv->dev);
|
||||
if (dev->devname == vmw_devname)
|
||||
dev->devname = NULL;
|
||||
ttm_object_device_release(&dev_priv->tdev);
|
||||
iounmap(dev_priv->mmio_virt);
|
||||
drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
|
||||
@ -500,7 +546,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
||||
struct drm_ioctl_desc *ioctl =
|
||||
&vmw_ioctls[nr - DRM_COMMAND_BASE];
|
||||
|
||||
if (unlikely(ioctl->cmd != cmd)) {
|
||||
if (unlikely(ioctl->cmd_drv != cmd)) {
|
||||
DRM_ERROR("Invalid command format, ioctl %d\n",
|
||||
nr - DRM_COMMAND_BASE);
|
||||
return -EINVAL;
|
||||
@ -589,6 +635,16 @@ static int vmw_master_set(struct drm_device *dev,
|
||||
struct vmw_master *vmaster = vmw_master(file_priv->master);
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv->enable_fb) {
|
||||
ret = vmw_3d_resource_inc(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
vmw_kms_save_vga(dev_priv);
|
||||
mutex_lock(&dev_priv->hw_mutex);
|
||||
vmw_write(dev_priv, SVGA_REG_TRACES, 0);
|
||||
mutex_unlock(&dev_priv->hw_mutex);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
BUG_ON(active != &dev_priv->fbdev_master);
|
||||
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
|
||||
@ -617,7 +673,13 @@ static int vmw_master_set(struct drm_device *dev,
|
||||
return 0;
|
||||
|
||||
out_no_active_lock:
|
||||
vmw_release_device(dev_priv);
|
||||
if (!dev_priv->enable_fb) {
|
||||
mutex_lock(&dev_priv->hw_mutex);
|
||||
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
|
||||
mutex_unlock(&dev_priv->hw_mutex);
|
||||
vmw_kms_restore_vga(dev_priv);
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -645,11 +707,23 @@ static void vmw_master_drop(struct drm_device *dev,
|
||||
|
||||
ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
|
||||
|
||||
if (!dev_priv->enable_fb) {
|
||||
ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
|
||||
if (unlikely(ret != 0))
|
||||
DRM_ERROR("Unable to clean VRAM on master drop.\n");
|
||||
mutex_lock(&dev_priv->hw_mutex);
|
||||
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
|
||||
mutex_unlock(&dev_priv->hw_mutex);
|
||||
vmw_kms_restore_vga(dev_priv);
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
dev_priv->active_master = &dev_priv->fbdev_master;
|
||||
ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
|
||||
ttm_vt_unlock(&dev_priv->fbdev_master.lock);
|
||||
|
||||
vmw_fb_on(dev_priv);
|
||||
if (dev_priv->enable_fb)
|
||||
vmw_fb_on(dev_priv);
|
||||
}
|
||||
|
||||
|
||||
@ -722,6 +796,7 @@ static struct drm_driver driver = {
|
||||
.irq_postinstall = vmw_irq_postinstall,
|
||||
.irq_uninstall = vmw_irq_uninstall,
|
||||
.irq_handler = vmw_irq_handler,
|
||||
.get_vblank_counter = vmw_get_vblank_counter,
|
||||
.reclaim_buffers_locked = NULL,
|
||||
.get_map_ofs = drm_core_get_map_ofs,
|
||||
.get_reg_ofs = drm_core_get_reg_ofs,
|
||||
|
@ -277,6 +277,7 @@ struct vmw_private {
|
||||
|
||||
bool stealth;
|
||||
bool is_opened;
|
||||
bool enable_fb;
|
||||
|
||||
/**
|
||||
* Master management.
|
||||
@ -285,6 +286,9 @@ struct vmw_private {
|
||||
struct vmw_master *active_master;
|
||||
struct vmw_master fbdev_master;
|
||||
struct notifier_block pm_nb;
|
||||
|
||||
struct mutex release_mutex;
|
||||
uint32_t num_3d_resources;
|
||||
};
|
||||
|
||||
static inline struct vmw_private *vmw_priv(struct drm_device *dev)
|
||||
@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
|
||||
return val;
|
||||
}
|
||||
|
||||
int vmw_3d_resource_inc(struct vmw_private *dev_priv);
|
||||
void vmw_3d_resource_dec(struct vmw_private *dev_priv);
|
||||
|
||||
/**
|
||||
* GMR utilities - vmwgfx_gmr.c
|
||||
*/
|
||||
@ -511,6 +518,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
|
||||
unsigned bbp, unsigned depth);
|
||||
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
|
||||
/**
|
||||
* Overlay control - vmwgfx_overlay.c
|
||||
|
@ -615,6 +615,11 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
|
||||
if (unlikely(ret != 0))
|
||||
goto err_unlock;
|
||||
|
||||
if (bo->mem.mem_type == TTM_PL_VRAM &&
|
||||
bo->mem.mm_node->start < bo->num_pages)
|
||||
(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
|
||||
false, false);
|
||||
|
||||
ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
|
||||
|
||||
/* Could probably bug on */
|
||||
|
@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
mutex_lock(&dev_priv->hw_mutex);
|
||||
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
|
||||
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
|
||||
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
|
||||
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
|
||||
|
||||
min = 4;
|
||||
@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
dev_priv->config_done_state);
|
||||
vmw_write(dev_priv, SVGA_REG_ENABLE,
|
||||
dev_priv->enable_state);
|
||||
vmw_write(dev_priv, SVGA_REG_TRACES,
|
||||
dev_priv->traces_state);
|
||||
|
||||
mutex_unlock(&dev_priv->hw_mutex);
|
||||
vmw_fence_queue_takedown(&fifo->fence_queue);
|
||||
|
@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
|
||||
save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
|
||||
save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
|
||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
||||
if (i == 0 && vmw_priv->num_displays == 1 &&
|
||||
save->width == 0 && save->height == 0) {
|
||||
|
||||
/*
|
||||
* It should be fairly safe to assume that these
|
||||
* values are uninitialized.
|
||||
*/
|
||||
|
||||
save->width = vmw_priv->vga_width - save->pos_x;
|
||||
save->height = vmw_priv->vga_height - save->pos_y;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -984,3 +996,8 @@ out_unlock:
|
||||
ttm_read_unlock(&vmaster->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "vmwgfx_kms.h"
|
||||
|
||||
#define VMWGFX_LDU_NUM_DU 8
|
||||
|
||||
#define vmw_crtc_to_ldu(x) \
|
||||
container_of(x, struct vmw_legacy_display_unit, base.crtc)
|
||||
#define vmw_encoder_to_ldu(x) \
|
||||
@ -536,6 +538,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
|
||||
|
||||
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (dev_priv->ldu_priv) {
|
||||
DRM_INFO("ldu system already on\n");
|
||||
return -EINVAL;
|
||||
@ -553,23 +559,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
|
||||
|
||||
drm_mode_create_dirty_info_property(dev_priv->dev);
|
||||
|
||||
vmw_ldu_init(dev_priv, 0);
|
||||
/* for old hardware without multimon only enable one display */
|
||||
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
|
||||
vmw_ldu_init(dev_priv, 1);
|
||||
vmw_ldu_init(dev_priv, 2);
|
||||
vmw_ldu_init(dev_priv, 3);
|
||||
vmw_ldu_init(dev_priv, 4);
|
||||
vmw_ldu_init(dev_priv, 5);
|
||||
vmw_ldu_init(dev_priv, 6);
|
||||
vmw_ldu_init(dev_priv, 7);
|
||||
for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
|
||||
vmw_ldu_init(dev_priv, i);
|
||||
ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
|
||||
} else {
|
||||
/* for old hardware without multimon only enable one display */
|
||||
vmw_ldu_init(dev_priv, 0);
|
||||
ret = drm_vblank_init(dev, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
if (!dev_priv->ldu_priv)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
|
||||
cmd->body.cid = cpu_to_le32(res->id);
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
static int vmw_context_init(struct vmw_private *dev_priv,
|
||||
@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
|
||||
cmd->body.cid = cpu_to_le32(res->id);
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
(void) vmw_3d_resource_inc(dev_priv);
|
||||
vmw_resource_activate(res, vmw_hw_context_destroy);
|
||||
return 0;
|
||||
}
|
||||
@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
|
||||
cmd->body.sid = cpu_to_le32(res->id);
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
vmw_3d_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
void vmw_surface_res_free(struct vmw_resource *res)
|
||||
@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
|
||||
}
|
||||
|
||||
vmw_fifo_commit(dev_priv, submit_size);
|
||||
(void) vmw_3d_resource_inc(dev_priv);
|
||||
vmw_resource_activate(res, vmw_hw_surface_destroy);
|
||||
return 0;
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ struct drm_gem_object {
|
||||
struct kref refcount;
|
||||
|
||||
/** Handle count of this object. Each handle also holds a reference */
|
||||
struct kref handlecount;
|
||||
atomic_t handle_count; /* number of handles on this object */
|
||||
|
||||
/** Related drm device */
|
||||
struct drm_device *dev;
|
||||
@ -808,7 +808,6 @@ struct drm_driver {
|
||||
*/
|
||||
int (*gem_init_object) (struct drm_gem_object *obj);
|
||||
void (*gem_free_object) (struct drm_gem_object *obj);
|
||||
void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
|
||||
|
||||
/* vga arb irq handler */
|
||||
void (*vgaarb_irq)(struct drm_device *dev, bool state);
|
||||
@ -1175,6 +1174,7 @@ extern int drm_release(struct inode *inode, struct file *filp);
|
||||
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
|
||||
extern void drm_vm_open_locked(struct vm_area_struct *vma);
|
||||
extern void drm_vm_close_locked(struct vm_area_struct *vma);
|
||||
extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
|
||||
extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
|
||||
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
||||
@ -1455,12 +1455,11 @@ int drm_gem_init(struct drm_device *dev);
|
||||
void drm_gem_destroy(struct drm_device *dev);
|
||||
void drm_gem_object_release(struct drm_gem_object *obj);
|
||||
void drm_gem_object_free(struct kref *kref);
|
||||
void drm_gem_object_free_unlocked(struct kref *kref);
|
||||
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
|
||||
size_t size);
|
||||
int drm_gem_object_init(struct drm_device *dev,
|
||||
struct drm_gem_object *obj, size_t size);
|
||||
void drm_gem_object_handle_free(struct kref *kref);
|
||||
void drm_gem_object_handle_free(struct drm_gem_object *obj);
|
||||
void drm_gem_vm_open(struct vm_area_struct *vma);
|
||||
void drm_gem_vm_close(struct vm_area_struct *vma);
|
||||
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
@ -1483,8 +1482,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
|
||||
static inline void
|
||||
drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
|
||||
{
|
||||
if (obj != NULL)
|
||||
kref_put(&obj->refcount, drm_gem_object_free_unlocked);
|
||||
if (obj != NULL) {
|
||||
struct drm_device *dev = obj->dev;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
kref_put(&obj->refcount, drm_gem_object_free);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int drm_gem_handle_create(struct drm_file *file_priv,
|
||||
@ -1495,7 +1498,7 @@ static inline void
|
||||
drm_gem_object_handle_reference(struct drm_gem_object *obj)
|
||||
{
|
||||
drm_gem_object_reference(obj);
|
||||
kref_get(&obj->handlecount);
|
||||
atomic_inc(&obj->handle_count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -1504,12 +1507,15 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj)
|
||||
if (obj == NULL)
|
||||
return;
|
||||
|
||||
if (atomic_read(&obj->handle_count) == 0)
|
||||
return;
|
||||
/*
|
||||
* Must bump handle count first as this may be the last
|
||||
* ref, in which case the object would disappear before we
|
||||
* checked for a name
|
||||
*/
|
||||
kref_put(&obj->handlecount, drm_gem_object_handle_free);
|
||||
if (atomic_dec_and_test(&obj->handle_count))
|
||||
drm_gem_object_handle_free(obj);
|
||||
drm_gem_object_unreference(obj);
|
||||
}
|
||||
|
||||
@ -1519,12 +1525,17 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
|
||||
if (obj == NULL)
|
||||
return;
|
||||
|
||||
if (atomic_read(&obj->handle_count) == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Must bump handle count first as this may be the last
|
||||
* ref, in which case the object would disappear before we
|
||||
* checked for a name
|
||||
*/
|
||||
kref_put(&obj->handlecount, drm_gem_object_handle_free);
|
||||
|
||||
if (atomic_dec_and_test(&obj->handle_count))
|
||||
drm_gem_object_handle_free(obj);
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,6 @@
|
||||
{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
|
||||
{0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
|
||||
{0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
|
||||
{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
|
||||
@ -103,6 +102,7 @@
|
||||
{0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
|
||||
{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
|
||||
{0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
|
||||
|
Loading…
Reference in New Issue
Block a user