From 72983ff30183745cd96760aa07b857c44daebde7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 27 Feb 2008 19:46:28 +0100 Subject: Don't wait for buffer idle before applying relocations. --- shared-core/i915_dma.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index b916441d..2d26fcc1 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -860,6 +860,15 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, drm_bo_kunmap(&relocatee->kmap); relocatee->data_page = NULL; relocatee->offset = new_cmd_offset; + + /* + * Note on buffer idle: + * Since we're applying relocations, this part of the + * buffer is obviously not used by the GPU and we don't + * need to wait for buffer idle. This is an important + * consideration for user-space buffer pools. + */ + ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, 1, &relocatee->kmap); if (ret) { @@ -1003,10 +1012,6 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, } mutex_lock (&relocatee.buf->mutex); - ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE); - if (ret) - goto out_err1; - while (reloc_user_ptr) { ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); if (ret) { -- cgit v1.2.3 From fd595fa4dc6f788a8a1e1b56178e15f411706cb9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 27 Feb 2008 21:44:40 +0100 Subject: Reinstate buffer idle before applying relocations. --- shared-core/i915_dma.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 2d26fcc1..f9e02c77 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -805,6 +805,7 @@ struct i915_relocatee_info { unsigned page_offset; struct drm_bo_kmap_obj kmap; int is_iomem; + int idle; }; struct drm_i915_validate_buffer { @@ -860,14 +861,13 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, drm_bo_kunmap(&relocatee->kmap); relocatee->data_page = NULL; relocatee->offset = new_cmd_offset; - - /* - * Note on buffer idle: - * Since we're applying relocations, this part of the - * buffer is obviously not used by the GPU and we don't - * need to wait for buffer idle. This is an important - * consideration for user-space buffer pools. - */ + + if (unlikely(!relocatee->idle)) { + ret = drm_bo_wait(relocatee->buf, 0, 0, 0); + if (ret) + return ret; + relocatee->idle = 1; + } ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, 1, &relocatee->kmap); -- cgit v1.2.3 From 132ba667f4a88bb182e2d2abc7c4e60699398380 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Feb 2008 12:59:39 +1000 Subject: drm: add a check for if modesetting is supported. This is Linux only code, it just uses sysfs to see if a control device has been registered on the requested PCI ID --- libdrm/xf86drmMode.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ libdrm/xf86drmMode.h | 1 + 2 files changed, 49 insertions(+) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 52fef81b..717e1fe2 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -41,6 +41,8 @@ #include "xf86drm.h" #include #include +#include +#include #define U642VOID(x) ((void *)(unsigned long)(x)) #define VOID2U64(x) ((uint64_t)(unsigned long)(x)) @@ -571,3 +573,49 @@ int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, return 0; } + +/* + * checks if a modesetting capable driver has attached to the pci id + * returns 0 if modesetting supported. + * -EINVAL or invalid bus id + * -ENOSYS if no modesetting support +*/ +int drmCheckModesettingSupported(const char *busid) +{ +#ifdef __linux__ + char pci_dev_dir[1024]; + char *bus_id_path; + char *bus_type; + int domain, bus, dev, func; + DIR *sysdir; + struct dirent *dent; + int found = 0, ret; + + ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); + if (ret != 4) + return -EINVAL; + + sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", + domain, bus, dev, func); + + sysdir = opendir(pci_dev_dir); + if (!sysdir) + return -EINVAL; + + dent = readdir(sysdir); + while (dent) { + if (!strncmp(dent->d_name, "drm:controlD", 12)) { + found = 1; + break; + } + + dent = readdir(sysdir); + } + + closedir(sysdir); + if (found) + return 0; +#endif + return -ENOSYS; + +} diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 7cc3ceca..71e779d4 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -243,3 +243,4 @@ extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, uint64_t value); +extern int drmCheckModesettingSupported(const char *busid); -- cgit v1.2.3 From 01dcc47d895997f77c9457558e974d41c23ed4e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Feb 2008 16:24:17 +1000 Subject: drm: add modesetting as a driver feature. This change adds a driver feature that for i915 is controlled by a module parameter. You now need to do insmod i915.ko modeset=1 to enable it the modesetting paths. It also fixes up lots of X paths. I can run my new DDX driver on this code with and without modesetting enabled --- linux-core/drmP.h | 1 + linux-core/drm_drv.c | 3 +- linux-core/drm_fops.c | 3 +- linux-core/drm_irq.c | 5 ++ linux-core/drm_stub.c | 9 +- linux-core/i915_drv.c | 10 ++- shared-core/i915_dma.c | 49 +++++++++-- shared-core/i915_init.c | 226 ++++++++++++++++++++++++++++-------------------- 8 files changed, 200 insertions(+), 106 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 51b02dc8..1a0a5659 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -106,6 +106,7 @@ struct drm_file; #define DRIVER_IRQ_SHARED 0x80 #define DRIVER_DMA_QUEUE 0x100 #define DRIVER_FB_DMA 0x200 +#define DRIVER_MODESET 0x400 /*@}*/ diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 4932ea59..dd76421f 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -414,7 +414,8 @@ static void drm_cleanup(struct drm_device * dev) drm_ht_remove(&dev->object_hash); drm_put_minor(&dev->primary); - drm_put_minor(&dev->control); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 5a74f424..fcadc544 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -481,7 +481,8 @@ int drm_release(struct inode *inode, struct file *filp) } mutex_unlock(&dev->ctxlist_mutex); - drm_fb_release(filp); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_fb_release(filp); file_priv->master = NULL; diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 637f5e1d..7dddbe19 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -261,6 +261,9 @@ int drm_irq_uninstall(struct drm_device * dev) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + mutex_lock(&dev->struct_mutex); irq_enabled = dev->irq_enabled; dev->irq_enabled = 0; @@ -306,6 +309,8 @@ int drm_control(struct drm_device *dev, void *data, case DRM_INST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != dev->irq) return -EINVAL; diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 334c8f03..6856075b 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -343,8 +343,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, goto err_g3; } - if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL))) - goto err_g3; + /* only add the control node on a modesetting platform */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL))) + goto err_g3; if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g4; @@ -361,7 +363,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, err_g5: drm_put_minor(&dev->primary); err_g4: - drm_put_minor(&dev->control); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); err_g3: if (!drm_fb_loaded) pci_disable_device(pdev); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 6c12f1a1..b844dfe6 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -39,6 +39,9 @@ static struct pci_device_id pciidlist[] = { i915_PCI_IDS }; +unsigned int i915_modeset = 0; +module_param_named(modeset, i915_modeset, int, 0400); + #ifdef I915_HAVE_FENCE extern struct drm_fence_driver i915_fence_driver; #endif @@ -563,8 +566,8 @@ static struct drm_driver driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .load = i915_driver_load, .unload = i915_driver_unload, -/* .lastclose = i915_driver_lastclose, - .preclose = i915_driver_preclose, */ + .lastclose = i915_driver_lastclose, + .preclose = i915_driver_preclose, .suspend = i915_suspend, .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, @@ -624,6 +627,9 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int __init i915_init(void) { driver.num_ioctls = i915_max_ioctl; + if (i915_modeset == 1) + driver.driver_features |= DRIVER_MODESET; + return drm_init(&driver, pciidlist); } diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index eee24dd1..20095a95 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -66,6 +66,11 @@ void i915_kernel_lost_context(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_ring_buffer *ring = &(dev_priv->ring); + /* we should never lose context on the ring with modesetting + * as we don't expose it to userspace */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail + 8); @@ -75,6 +80,11 @@ void i915_kernel_lost_context(struct drm_device * dev) int i915_dma_cleanup(struct drm_device * dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. @@ -82,6 +92,28 @@ int i915_dma_cleanup(struct drm_device * dev) if (dev->irq) drm_irq_uninstall(dev); + if (dev_priv->ring.virtual_start) { + drm_core_ioremapfree(&dev_priv->ring.map, dev); + dev_priv->ring.virtual_start = 0; + dev_priv->ring.map.handle = 0; + dev_priv->ring.map.size = 0; + dev_priv->ring.Size = 0; + } + + if (dev_priv->status_page_dmah) { + drm_pci_free(dev, dev_priv->status_page_dmah); + dev_priv->status_page_dmah = NULL; + /* Need to rewrite hardware status page */ + I915_WRITE(0x02080, 0x1ffff000); + } + + if (dev_priv->status_gfx_addr) { + dev_priv->status_gfx_addr = 0; + drm_core_ioremapfree(&dev_priv->hws_map, dev); + I915_WRITE(0x02080, 0x1ffff000); + } + + return 0; } @@ -153,13 +185,17 @@ static int i915_initialize(struct drm_device * dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; - dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio_map) { - i915_dma_cleanup(dev); - DRM_ERROR("can not find mmio map!\n"); - return -EINVAL; + if (!drm_core_check_feature(dev, DRIVER_MODESET)) { + if (init->mmio_offset != 0) + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); + if (!dev_priv->mmio_map) { + i915_dma_cleanup(dev); + DRM_ERROR("can not find mmio map!\n"); + return -EINVAL; + } } + #ifdef I915_HAVE_BUFFER dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; #endif @@ -246,6 +282,9 @@ static int i915_dma_resume(struct drm_device * dev) DRM_DEBUG("\n"); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + if (!dev_priv->mmio_map) { DRM_ERROR("can not find mmio map!\n"); return -EINVAL; diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index b2d3f0d0..a2e08bc1 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -153,106 +153,113 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base); ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, - _DRM_REGISTERS, _DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map); + _DRM_REGISTERS, _DRM_KERNEL|_DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map); if (ret != 0) { DRM_ERROR("Cannot add mapping for MMIO registers\n"); return ret; } +#ifdef __linux__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + intel_init_chipset_flush_compat(dev); +#endif +#endif + /* * Initialize the memory manager for local and AGP space */ drm_bo_driver_init(dev); - i915_probe_agp(dev->pdev, &agp_size, &prealloc_size); - printk("setting up %ld bytes of VRAM space\n", prealloc_size); - printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size)); - drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT, 1); - drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT, 1); - - I915_WRITE(LP_RING + RING_LEN, 0); - I915_WRITE(LP_RING + RING_HEAD, 0); - I915_WRITE(LP_RING + RING_TAIL, 0); - - size = PRIMARY_RINGBUFFER_SIZE; - ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, - DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_VRAM | - DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, 0x1, 0, - &dev_priv->ring_buffer); - if (ret < 0) { - DRM_ERROR("Unable to allocate or pin ring buffer\n"); - return -EINVAL; - } - - /* remap the buffer object properly */ - dev_priv->ring.Start = dev_priv->ring_buffer->offset; - dev_priv->ring.End = dev_priv->ring.Start + size; - dev_priv->ring.Size = size; - dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; - - /* FIXME: need wrapper with PCI mem checks */ - ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem, - (void **) &dev_priv->ring.virtual_start); - if (ret) - DRM_ERROR("error mapping ring buffer: %d\n", ret); - - DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start, - dev_priv->ring.virtual_start, dev_priv->ring.Size); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + i915_probe_agp(dev->pdev, &agp_size, &prealloc_size); + printk("setting up %ld bytes of VRAM space\n", prealloc_size); + printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size)); + drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT, 1); + drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT, 1); + + I915_WRITE(LP_RING + RING_LEN, 0); + I915_WRITE(LP_RING + RING_HEAD, 0); + I915_WRITE(LP_RING + RING_TAIL, 0); + + size = PRIMARY_RINGBUFFER_SIZE; + ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, 0x1, 0, + &dev_priv->ring_buffer); + if (ret < 0) { + DRM_ERROR("Unable to allocate or pin ring buffer\n"); + return -EINVAL; + } + + /* remap the buffer object properly */ + dev_priv->ring.Start = dev_priv->ring_buffer->offset; + dev_priv->ring.End = dev_priv->ring.Start + size; + dev_priv->ring.Size = size; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + + /* FIXME: need wrapper with PCI mem checks */ + ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem, + (void **) &dev_priv->ring.virtual_start); + if (ret) + DRM_ERROR("error mapping ring buffer: %d\n", ret); + + DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start, + dev_priv->ring.virtual_start, dev_priv->ring.Size); // - memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size); - - I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start); - I915_WRITE(LP_RING + RING_LEN, - ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | - (RING_NO_REPORT | RING_VALID)); - - /* We are using separate values as placeholders for mechanisms for - * private backbuffer/depthbuffer usage. - */ - dev_priv->use_mi_batchbuffer_start = 0; + memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size); + + I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start); + I915_WRITE(LP_RING + RING_LEN, + ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | + (RING_NO_REPORT | RING_VALID)); + + /* We are using separate values as placeholders for mechanisms for + * private backbuffer/depthbuffer usage. + */ + dev_priv->use_mi_batchbuffer_start = 0; + + /* Allow hardware batchbuffers unless told otherwise. + */ + dev_priv->allow_batchbuffer = 1; + + /* Program Hardware Status Page */ + if (!IS_G33(dev)) { + dev_priv->status_page_dmah = + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + + if (!dev_priv->status_page_dmah) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("Can not allocate hardware status page\n"); + return -ENOMEM; + } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + + I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page); + } + DRM_DEBUG("Enabled hardware status page\n"); - /* Allow hardware batchbuffers unless told otherwise. - */ - dev_priv->allow_batchbuffer = 1; - - /* Program Hardware Status Page */ - if (!IS_G33(dev)) { - dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); - - if (!dev_priv->status_page_dmah) { - dev->dev_private = (void *)dev_priv; - i915_dma_cleanup(dev); - DRM_ERROR("Can not allocate hardware status page\n"); - return -ENOMEM; + dev_priv->wq = create_singlethread_workqueue("i915"); + if (dev_priv == 0) { + DRM_DEBUG("Error\n"); } - dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; - dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + intel_modeset_init(dev); + drm_initial_config(dev, false); - I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page); - } - DRM_DEBUG("Enabled hardware status page\n"); + drm_mm_print(&dev->bm.man[DRM_BO_MEM_VRAM].manager, "VRAM"); + drm_mm_print(&dev->bm.man[DRM_BO_MEM_TT].manager, "TT"); - dev_priv->wq = create_singlethread_workqueue("i915"); - if (dev_priv == 0) { - DRM_DEBUG("Error\n"); + drm_irq_install(dev); } - - intel_modeset_init(dev); - drm_initial_config(dev, false); - - drm_mm_print(&dev->bm.man[DRM_BO_MEM_VRAM].manager, "VRAM"); - drm_mm_print(&dev->bm.man[DRM_BO_MEM_TT].manager, "TT"); - - drm_irq_install(dev); - return 0; } @@ -262,7 +269,10 @@ int i915_driver_unload(struct drm_device *dev) I915_WRITE(LP_RING + RING_LEN, 0); - intel_modeset_cleanup(dev); + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + intel_modeset_cleanup(dev); + } #if 0 if (dev_priv->ring.virtual_start) { @@ -298,25 +308,33 @@ int i915_driver_unload(struct drm_device *dev) I915_WRITE(I915REG_HWS_PGA, 0x1ffff000); } - drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem, - dev_priv->ring.virtual_start); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem, + dev_priv->ring.virtual_start); - DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage)); - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&dev_priv->ring_buffer); + DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage)); + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(&dev_priv->ring_buffer); - if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { - DRM_ERROR("Memory manager type 3 not clean. " - "Delaying takedown\n"); - } - if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) { - DRM_ERROR("Memory manager type 3 not clean. " - "Delaying takedown\n"); + if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { + DRM_ERROR("Memory manager type 3 not clean. " + "Delaying takedown\n"); + } + if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) { + DRM_ERROR("Memory manager type 3 not clean. " + "Delaying takedown\n"); + } + mutex_unlock(&dev->struct_mutex); } - mutex_unlock(&dev->struct_mutex); drm_bo_driver_finish(dev); +#ifdef __linux__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + intel_init_chipset_flush_compat(dev); +#endif +#endif + DRM_DEBUG("%p\n", dev_priv->mmio_map); drm_rmmap(dev, dev_priv->mmio_map); @@ -363,3 +381,23 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) master->driver_priv = NULL; } + +void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_mem_release(dev, file_priv, dev_priv->agp_heap); +} + +void i915_driver_lastclose(struct drm_device * dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + if (dev_priv->agp_heap) + i915_mem_takedown(&(dev_priv->agp_heap)); + + i915_dma_cleanup(dev); +} -- cgit v1.2.3 From 8ef838e5ff7b3c005d7fbc725e17bcccd0e1e1eb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 28 Feb 2008 13:47:15 +0100 Subject: Add a compat kmap_atomic_prot_pfn to do quick kernel map / unmaps of PCI- or high memory. This is substantially more efficient than drm_bo_kmap, since the mapping only lives on a single processor. Unmapping is done use kunmap_atomic(). Flushes only a single tlb() entry. Add a support utility int drm_bo_pfn_prot() that returns the pfn and desired page protection for a given bo offset. This is all intended for relocations in bound TTMS or vram. Mapping-accessing-unmapping must be atomic, either using preempt_xx() macros or a spinlock. --- linux-core/drm_bo_move.c | 33 +++++++++++++++++++++++++++++++++ linux-core/drm_compat.c | 32 ++++++++++++++++++++++++++++++++ linux-core/drm_compat.h | 5 +++++ linux-core/drm_objects.h | 4 ++++ 4 files changed, 74 insertions(+) diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index b06a09f0..30e0f43f 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -595,3 +595,36 @@ void drm_bo_kunmap(struct drm_bo_kmap_obj *map) map->page = NULL; } EXPORT_SYMBOL(drm_bo_kunmap); + +int drm_bo_pfn_prot(struct drm_buffer_object *bo, + unsigned long dst_offset, + unsigned long *pfn, + pgprot_t *prot) +{ + struct drm_bo_mem_reg *mem = &bo->mem; + struct drm_device *dev = bo->dev; + unsigned long bus_offset; + unsigned long bus_size; + unsigned long bus_base; + struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type]; + int ret; + + ret = drm_bo_pci_offset(dev, mem, &bus_base, &bus_offset, + &bus_size); + if (ret) + return -EINVAL; + + if (bus_size != 0) + *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT; + else if (!bo->ttm) + return -EINVAL; + else + *pfn = page_to_pfn(drm_ttm_get_page(bo->ttm, dst_offset >> PAGE_SHIFT)); + + *prot = (mem->flags & DRM_BO_FLAG_CACHED) ? + PAGE_KERNEL : drm_kernel_io_prot(man->drm_bus_maptype); + + return 0; +} +EXPORT_SYMBOL(drm_bo_pfn_prot); + diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index a745a7d9..32e43a0a 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -729,3 +729,35 @@ void *idr_replace(struct idr *idp, void *ptr, int id) } EXPORT_SYMBOL(idr_replace); #endif + +#if defined(CONFIG_X86) + +#define drm_kmap_get_fixmap_pte(vaddr) \ + pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr)) + +void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, + pgprot_t protection) +{ + enum fixed_addresses idx; + unsigned long vaddr; + static pte_t *km_pte; + static int initialized = 0; + + if (unlikely(!initialized)) { + km_pte = drm_kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN)); + initialized = 1; + } + + pagefault_disable(); + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + set_pte(km_pte-idx, pfn_pte(pfn, protection)); + + return (void*) vaddr; +} + +EXPORT_SYMBOL(kmap_atomic_prot_pfn); + +#endif + + diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index f8933e0c..39027cf4 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -328,4 +328,9 @@ void *idr_replace(struct idr *idp, void *ptr, int id); typedef _Bool bool; #endif +#if defined(CONFIG_X86) +#define DRM_KMAP_ATOMIC_PROT_PFN +extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, + pgprot_t protection); +#endif #endif diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index e43e8dfd..8055afe1 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -738,6 +738,10 @@ static inline void *drm_bmo_virtual(struct drm_bo_kmap_obj *map, int *is_iomem) extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map); extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page, unsigned long num_pages, struct drm_bo_kmap_obj *map); +extern int drm_bo_pfn_prot(struct drm_buffer_object *bo, + unsigned long dst_offset, + unsigned long *pfn, + pgprot_t *prot); /* -- cgit v1.2.3 From cdbd616ea5f0ee491ff82cac74b918a14b039917 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Feb 2008 10:16:24 +1000 Subject: agp: export the correct symbol --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 02187017..f58d5516 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -666,7 +666,7 @@ void drm_agp_chipset_flush(struct drm_device *dev) { agp_flush_chipset(dev->agp->bridge); } -EXPORT_SYMBOL(drm_agp_flush_chipset); +EXPORT_SYMBOL(drm_agp_chipset_flush); #endif #endif /* __OS_HAS_AGP */ -- cgit v1.2.3 From 0e72819629741339af46d0e303f33482acdf0972 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Feb 2008 14:07:29 +1000 Subject: drm: change fb api to take a bo handle not the bo pointer. --- libdrm/xf86drmMode.c | 5 +++-- libdrm/xf86drmMode.h | 2 +- tests/mode/modetest.c | 2 +- tests/modedemo/demo.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 717e1fe2..dd1a6ca9 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -203,7 +203,8 @@ uint32_t drmModeGetHotplug(int fd) } int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, - uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id) + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id) { struct drm_mode_fb_cmd f; int ret; @@ -213,7 +214,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, f.pitch = pitch; f.bpp = bpp; f.depth = depth; - f.handle = bo->handle; + f.handle = bo_handle; if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)) return ret; diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 71e779d4..edf9efee 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -177,7 +177,7 @@ extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId); * Creates a new framebuffer with an buffer object as its scanout buffer. */ extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, - uint8_t bpp, uint32_t pitch, drmBO *bo, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id); /** * Destroies the given framebuffer. diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c index ab0cdc9c..a50b0cc5 100644 --- a/tests/mode/modetest.c +++ b/tests/mode/modetest.c @@ -291,7 +291,7 @@ int testFrameBufferAdd(int fd, drmModeResPtr res) goto err; printf("\tAdding FB\n"); - ret = drmModeAddFB(fd, 800, 600, 32, 8, 0, &bo, &fb); + ret = drmModeAddFB(fd, 800, 600, 32, 8, 0, bo->handle, &fb); if (ret) goto err_bo; diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c index db51cd66..00020bde 100644 --- a/tests/modedemo/demo.c +++ b/tests/modedemo/demo.c @@ -483,7 +483,7 @@ drmModeFBPtr createFB(int fd, drmModeResPtr res) goto err; } - ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, &bo, &fb); + ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, bo->handle, &fb); if (ret) goto err_bo; -- cgit v1.2.3 From 1d068973d5f5e6d8d14b4c0c6e28588107aafc6f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Feb 2008 13:31:14 +0100 Subject: Fix compilation breakage on x86-64. --- linux-core/drm_compat.c | 3 +-- linux-core/drm_compat.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index 32e43a0a..eb6c5d81 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -730,8 +730,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id) EXPORT_SYMBOL(idr_replace); #endif -#if defined(CONFIG_X86) - +#if defined(DRM_KMAP_ATOMIC_PROT_PFN) #define drm_kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr)) diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 39027cf4..08892e6b 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -328,7 +328,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id); typedef _Bool bool; #endif -#if defined(CONFIG_X86) +#if (defined(CONFIG_X86) && defined(CONFIG_X86_32)) #define DRM_KMAP_ATOMIC_PROT_PFN extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t protection); -- cgit v1.2.3 From 09999c90ab1bf3f7d8b277895c962c8a7b3afc18 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Fri, 29 Feb 2008 21:57:40 +0100 Subject: FIX_KMAP_BEGIN requires CONFIG_HIMEM (see include/asm-i386.h/fixmap.h) --- linux-core/drm_compat.c | 2 +- linux-core/drm_compat.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index eb6c5d81..d4044cbd 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -730,7 +730,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id) EXPORT_SYMBOL(idr_replace); #endif -#if defined(DRM_KMAP_ATOMIC_PROT_PFN) +#if defined(DRM_KMAP_ATOMIC_PROT_PFN) && defined(CONFIG_HIMEM) #define drm_kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr)) diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 08892e6b..136a7296 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -328,7 +328,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id); typedef _Bool bool; #endif -#if (defined(CONFIG_X86) && defined(CONFIG_X86_32)) +#if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIMEM)) #define DRM_KMAP_ATOMIC_PROT_PFN extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t protection); -- cgit v1.2.3 From 9c5ba9f5d153877ab2e7cb623cab5607aa5cd4a8 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Sun, 2 Mar 2008 21:48:40 +0000 Subject: Add FENCE registers to MMIO list --- shared-core/i915_dma.c | 10 ++++++++++ shared-core/i915_drm.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 20095a95..28835a04 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1469,6 +1469,16 @@ drm_i915_mmio_entry_t mmio_table[] = { I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE, 0x30010, 6 + }, + [MMIO_REGS_FENCE] = { + I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE, + 0x2000, + 8 + }, + [MMIO_REGS_FENCE_NEW] = { + I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE, + 0x3000, + 16 } }; diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index a40cabdc..824aee27 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -328,6 +328,8 @@ typedef struct drm_i915_vblank_swap { #define MMIO_REGS_PS_DEPTH_COUNT 8 #define MMIO_REGS_DOVSTA 9 #define MMIO_REGS_GAMMA 10 +#define MMIO_REGS_FENCE 11 +#define MMIO_REGS_FENCE_NEW 12 typedef struct drm_i915_mmio_entry { unsigned int flag; -- cgit v1.2.3 From 63fd6f284ddd1096d34b39941683ae244c1e01fc Mon Sep 17 00:00:00 2001 From: Zou Nan hai Date: Mon, 3 Mar 2008 14:49:49 +0800 Subject: [i915] 2D driver may reset Frame count value, this may lead driver to leap it's vblank count a huge value. This will stall some applications that switch video mode if vblank_mode is set to a non zero value in drirc. --- shared-core/i915_irq.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index fd08b6e8..126f0379 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -406,6 +406,13 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) if (i915_in_vblank(dev, pipe)) count++; #endif + /* count may be reset by other driver(e.g. 2D driver), + we have no way to know if it is wrapped or resetted + when count is zero. do a rough guess. + */ + if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2) + dev->last_vblank[pipe] = 0; + return count; } -- cgit v1.2.3 From eedf3fa2f08eb774a36109c2fbda7207bf83fbe9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Mar 2008 12:16:51 -0800 Subject: Don't shortcut the info syscall for drmBOBusy on nonshareable objects. This broke the results when you're trying to check if a buffer you dispatched some time ago is done being rendered from. --- libdrm/xf86drm.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index e3550de7..fb8f1c66 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2799,23 +2799,18 @@ int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint) } return 0; } - + int drmBOBusy(int fd, drmBO *buf, int *busy) { - if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) && - !(buf->replyFlags & DRM_BO_REP_BUSY)) { - *busy = 0; - return 0; - } - else { - int ret = drmBOInfo(fd, buf); - if (ret) - return ret; - *busy = (buf->replyFlags & DRM_BO_REP_BUSY); - return 0; - } + int ret = drmBOInfo(fd, buf); + + if (ret) + return ret; + + *busy = (buf->replyFlags & DRM_BO_REP_BUSY); + return 0; } - + int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, unsigned memType) { -- cgit v1.2.3 From d41846adb72ba89c94ea1164e366032b1d36bd55 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Mar 2008 13:35:23 -0800 Subject: Clarify through the names what drm_ttm_alloc_pages() and friend actually did. These are all about the page directory (pointers to pages) rather than the actual pages backing the allocation. --- linux-core/drm_objects.h | 2 +- linux-core/drm_ttm.c | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 8055afe1..69a5c27f 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -384,7 +384,7 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm); * The array of page pointers was allocated with vmalloc * instead of drm_calloc. */ -#define DRM_TTM_PAGE_VMALLOC (1 << 4) +#define DRM_TTM_PAGEDIR_VMALLOC (1 << 4) /* * This ttm is mapped from user space */ diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index a9d87338..cc80b132 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -42,11 +42,12 @@ void drm_ttm_cache_flush(void) } EXPORT_SYMBOL(drm_ttm_cache_flush); -/* - * Use kmalloc if possible. Otherwise fall back to vmalloc. +/** + * Allocates storage for pointers to the pages that back the ttm. + * + * Uses kmalloc if possible. Otherwise falls back to vmalloc. */ - -static void drm_ttm_alloc_pages(struct drm_ttm *ttm) +static void drm_ttm_alloc_page_directory(struct drm_ttm *ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); ttm->pages = NULL; @@ -60,19 +61,19 @@ static void drm_ttm_alloc_pages(struct drm_ttm *ttm) if (!ttm->pages) { ttm->pages = vmalloc_user(size); if (ttm->pages) - ttm->page_flags |= DRM_TTM_PAGE_VMALLOC; + ttm->page_flags |= DRM_TTM_PAGEDIR_VMALLOC; } if (!ttm->pages) drm_free_memctl(size); } -static void drm_ttm_free_pages(struct drm_ttm *ttm) +static void drm_ttm_free_page_directory(struct drm_ttm *ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); - if (ttm->page_flags & DRM_TTM_PAGE_VMALLOC) { + if (ttm->page_flags & DRM_TTM_PAGEDIR_VMALLOC) { vfree(ttm->pages); - ttm->page_flags &= ~DRM_TTM_PAGE_VMALLOC; + ttm->page_flags &= ~DRM_TTM_PAGEDIR_VMALLOC; } else { drm_free(ttm->pages, size, DRM_MEM_TTM); } @@ -215,7 +216,7 @@ int drm_ttm_destroy(struct drm_ttm *ttm) else drm_ttm_free_alloced_pages(ttm); - drm_ttm_free_pages(ttm); + drm_ttm_free_page_directory(ttm); } drm_ctl_free(ttm, sizeof(*ttm), DRM_MEM_TTM); @@ -349,7 +350,7 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, * Account also for AGP module memory usage. */ - drm_ttm_alloc_pages(ttm); + drm_ttm_alloc_page_directory(ttm); if (!ttm->pages) { drm_ttm_destroy(ttm); DRM_ERROR("Failed allocating page table\n"); -- cgit v1.2.3 From 3332a0add63162222bd9c829117cd7e30d981aa7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Jan 2008 19:02:56 -0800 Subject: Remove unused DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS. --- shared-core/drm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/shared-core/drm.h b/shared-core/drm.h index 6c134566..213d3c7a 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -646,7 +646,6 @@ struct drm_set_version { #define DRM_FENCE_FLAG_EMIT 0x00000001 #define DRM_FENCE_FLAG_SHAREABLE 0x00000002 #define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004 -#define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008 #define DRM_FENCE_FLAG_NO_USER 0x00000010 /* Reserved for driver use */ -- cgit v1.2.3 From a6a2f2c8c491617de702dc7d62bb55cbada4d42b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Mar 2008 13:45:41 -0800 Subject: Clarify when WAIT_LAZY is relevant to users. --- shared-core/drm.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/shared-core/drm.h b/shared-core/drm.h index 213d3c7a..663696c1 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -645,6 +645,13 @@ struct drm_set_version { #define DRM_FENCE_FLAG_EMIT 0x00000001 #define DRM_FENCE_FLAG_SHAREABLE 0x00000002 +/** + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. + */ #define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004 #define DRM_FENCE_FLAG_NO_USER 0x00000010 @@ -794,13 +801,12 @@ struct drm_fence_arg { * with it as a result of this operation */ #define DRM_BO_HINT_DONT_FENCE 0x00000004 -/* - * Sleep while waiting for the operation to complete. - * Without this flag, the kernel will, instead, spin - * until this operation has completed. I'm not sure - * why you would ever want this, so please always - * provide DRM_BO_HINT_WAIT_LAZY to any operation - * which may block +/** + * On hardware with no interrupt events for operation completion, + * indicates that the kernel should sleep while waiting for any blocking + * operation to complete rather than spinning. + * + * Has no effect otherwise. */ #define DRM_BO_HINT_WAIT_LAZY 0x00000008 /* -- cgit v1.2.3 From 81db48536c9d7bb23c448af6a6f1de81df755585 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Mar 2008 10:31:43 +1000 Subject: remove unused functions + include header file --- libdrm/xf86drmMode.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index dd1a6ca9..30b434de 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -36,6 +36,7 @@ * platforms find which headers to include to get uint32_t */ #include +#include #include "xf86drmMode.h" #include "xf86drm.h" @@ -68,27 +69,6 @@ void* drmAllocCpy(void *array, int count, int entry_size) return r; } -/** - * Generate crtc and output ids. - * - * Will generate ids starting from 1 up to count if count is greater then 0. - */ -static uint32_t* drmAllocGenerate(int count) -{ - uint32_t *r; - int i; - - if(0 <= count) - return 0; - - if (!(r = drmMalloc(count*sizeof(*r)))) - return 0; - - for (i = 0; i < count; r[i] = ++i); - - return 0; -} - /* * A couple of free functions. */ -- cgit v1.2.3 From 4aa7efe398911bd58fb348703444a92114e45114 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Mar 2008 10:41:54 +1000 Subject: libdrm: fix warnings in mode code --- libdrm/xf86drmMode.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 30b434de..07b14dbf 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -37,6 +37,7 @@ */ #include #include +#include #include "xf86drmMode.h" #include "xf86drm.h" @@ -125,7 +126,6 @@ void drmModeFreeOutput(drmModeOutputPtr ptr) drmModeResPtr drmModeGetResources(int fd) { struct drm_mode_card_res res; - int i; drmModeResPtr r = 0; memset(&res, 0, sizeof(struct drm_mode_card_res)); @@ -196,7 +196,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, f.depth = depth; f.handle = bo_handle; - if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)) + if ((ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))) return ret; *buf_id = f.buffer_id; @@ -243,7 +243,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) { struct drm_mode_crtc crtc; drmModeCrtcPtr r; - int i = 0; crtc.count_outputs = 0; crtc.outputs = 0; @@ -276,10 +275,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) r->possibles = crtc.possibles; return r; - -err_allocs: - - return 0; } @@ -433,8 +428,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) { struct drm_mode_get_property prop; drmModePropertyPtr r; - struct drm_mode_property_blob *blob_tmp; - int i; + prop.prop_id = property_id; prop.count_enum_blobs = 0; prop.count_values = 0; @@ -549,7 +543,7 @@ int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, osp.prop_id = property_id; osp.value = value; - if (ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)) + if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp))) return ret; return 0; @@ -565,8 +559,6 @@ int drmCheckModesettingSupported(const char *busid) { #ifdef __linux__ char pci_dev_dir[1024]; - char *bus_id_path; - char *bus_type; int domain, bus, dev, func; DIR *sysdir; struct dirent *dent; -- cgit v1.2.3 From 4dbf447f4305e3c2aa8914b5ccfc07d9bf8ef28e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Mar 2008 15:28:38 +1000 Subject: drm: fixup compat with old x.org drivers --- linux-core/drm_drv.c | 15 ++++++++++++--- linux-core/i915_drv.c | 5 +++-- shared-core/i915_init.c | 9 +++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index dd76421f..434789dd 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -187,7 +187,9 @@ int drm_lastclose(struct drm_device * dev) DRM_DEBUG("\n"); -/* return 0; */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + drm_bo_driver_finish(dev); + /* * We can't do much about this function failing. */ @@ -425,13 +427,20 @@ int drm_minors_cleanup(int id, void *ptr, void *data) struct drm_minor *minor = ptr; struct drm_device *dev; struct drm_driver *driver = data; - if (id < 127 || id > 192) - return 0; dev = minor->dev; if (minor->dev->driver != driver) return 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (minor->type != DRM_MINOR_CONTROL) + return 0; + } else { + if (minor->type != DRM_MINOR_LEGACY) + return 0; + } + + if (dev) pci_dev_put(dev->pdev); drm_cleanup(dev); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index b844dfe6..0e65c0cd 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -48,8 +48,8 @@ extern struct drm_fence_driver i915_fence_driver; #ifdef I915_HAVE_BUFFER -static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; -static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL}; +static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; +static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL}; static struct drm_bo_driver i915_bo_driver = { .mem_type_prio = i915_mem_prios, @@ -566,6 +566,7 @@ static struct drm_driver driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .load = i915_driver_load, .unload = i915_driver_unload, + .firstopen = i915_driver_firstopen, .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .suspend = i915_suspend, diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index a2e08bc1..1f22d171 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -401,3 +401,12 @@ void i915_driver_lastclose(struct drm_device * dev) i915_dma_cleanup(dev); } + +int i915_driver_firstopen(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + + drm_bo_driver_init(dev); + return 0; +} -- cgit v1.2.3 From f78cdac8e512642db1aaf09bf9178e23ede25586 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Mar 2008 15:28:59 +1000 Subject: fixup previous merge --- linux-core/drm_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index b7b8e395..9b982662 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -806,5 +806,5 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, } EXPORT_SYMBOL(kmap_atomic_prot_pfn); - +#endif -- cgit v1.2.3 From 638353103d009d44bd5bdbe97cc7cef1bf011cdf Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Wed, 5 Mar 2008 15:08:46 +0800 Subject: i915: Evict if relocatee buffer is CACHED_MAPPED before writting relocations, otherwise the GPU probably sees some inconsistent data. Fix fd.o bug#14656 --- linux-core/drm_bo.c | 3 ++- linux-core/drm_objects.h | 2 +- shared-core/i915_dma.c | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 3b180d15..17180d8d 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1066,7 +1066,7 @@ static int drm_bo_busy(struct drm_buffer_object *bo) return 0; } -static int drm_bo_evict_cached(struct drm_buffer_object *bo) +int drm_bo_evict_cached(struct drm_buffer_object *bo) { int ret = 0; @@ -1076,6 +1076,7 @@ static int drm_bo_evict_cached(struct drm_buffer_object *bo) return ret; } +EXPORT_SYMBOL(drm_bo_evict_cached); /* * Wait until a buffer is unmapped. */ diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 69a5c27f..fd32f0f4 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -697,7 +697,7 @@ extern int drm_bo_do_validate(struct drm_buffer_object *bo, uint64_t flags, uint64_t mask, uint32_t hint, uint32_t fence_class, struct drm_bo_info_rep *rep); - +extern int drm_bo_evict_cached(struct drm_buffer_object *bo); /* * Buffer object memory move- and map helpers. * drm_bo_move.c diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index f9e02c77..9e474bc6 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -806,6 +806,7 @@ struct i915_relocatee_info { struct drm_bo_kmap_obj kmap; int is_iomem; int idle; + int evicted; }; struct drm_i915_validate_buffer { @@ -878,6 +879,12 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, &relocatee->is_iomem); relocatee->page_offset = (relocatee->offset & PAGE_MASK); + + if (!relocatee->evicted && + relocatee->buf->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) { + drm_bo_evict_cached(relocatee->buf); + relocatee->evicted = 1; + } } val = buffers[buf_index].buffer->offset; -- cgit v1.2.3 From a875821f7b19a1bcee238cef5c3b507d2869542d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 5 Mar 2008 19:25:03 +1000 Subject: drm: Fix for non-coherent DMA PowerPC This patch fixes bits of the DRM so to make the radeon DRI work on non-cache coherent PCI DMA variants of the PowerPC processors. It moves the few places that needs change to wrappers to that other architectures with similar issues can easily add their own changes to those wrappers, at least until we have more useful generic kernel API. Signed-off-by: Benjamin Herrenschmidt --- linux-core/ati_pcigart.c | 6 ++++++ linux-core/drm_scatter.c | 11 ++++++++++- linux-core/drm_vm.c | 19 ++++++++++++++----- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index 68029635..93519e5f 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -224,6 +224,12 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga } } + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) + dma_sync_single_for_device(&dev->pdev->dev, + bus_address, + max_pages * sizeof(u32), + PCI_DMA_TODEVICE); + ret = 1; #if defined(__i386__) || defined(__x86_64__) diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c index 77b9f95d..dfae4b84 100644 --- a/linux-core/drm_scatter.c +++ b/linux-core/drm_scatter.c @@ -36,6 +36,15 @@ #define DEBUG_SCATTER 0 +static inline void *drm_vmalloc_dma(unsigned long size) +{ +#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) + return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE); +#else + return vmalloc_32(size); +#endif +} + void drm_sg_cleanup(struct drm_sg_mem *entry) { struct page *page; @@ -105,7 +114,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) } memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr)); - entry->virtual = vmalloc_32(pages << PAGE_SHIFT); + entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT); if (!entry->virtual) { drm_free(entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES); diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 15e1c0f5..ffda8284 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -59,17 +59,27 @@ pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) pgprot_val(tmp) |= _PAGE_NO_CACHE; if (map_type == _DRM_REGISTERS) pgprot_val(tmp) |= _PAGE_GUARDED; -#endif -#if defined(__ia64__) +#elif defined(__ia64__) if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) tmp = pgprot_writecombine(tmp); else tmp = pgprot_noncached(tmp); +#elif defined(__sparc__) + tmp = pgprot_noncached(tmp); #endif return tmp; } +static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) +{ + pgprot_t tmp = vm_get_page_prot(vma->vm_flags); + +#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) + tmp |= _PAGE_NO_CACHE; +#endif + return tmp; +} /** * \c nopage method for AGP virtual memory. @@ -628,9 +638,6 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) offset = dev->driver->get_reg_ofs(dev); vma->vm_flags |= VM_IO; /* not in core dump */ vma->vm_page_prot = drm_io_prot(map->type, vma); -#ifdef __sparc__ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -#endif if (io_remap_pfn_range(vma, vma->vm_start, (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, @@ -649,6 +656,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) page_to_pfn(virt_to_page(map->handle)), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + vma->vm_page_prot = drm_dma_prot(map->type, vma); /* fall through to _DRM_SHM */ case _DRM_SHM: vma->vm_ops = &drm_vm_shm_ops; @@ -661,6 +669,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &drm_vm_sg_ops; vma->vm_private_data = (void *)map; vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = drm_dma_prot(map->type, vma); break; case _DRM_TTM: return drm_bo_mmap_locked(vma, filp, map); -- cgit v1.2.3 From 12574590cdf7871755d1939463ca6898251fd0d1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 6 Mar 2008 05:21:50 +1000 Subject: drm: reorganise minor number handling using code from modesetting branch Rip out the whole head thing and replace it with an idr and drm_minor structure. --- linux-core/drmP.h | 42 ++++++------ linux-core/drm_agpsupport.c | 2 +- linux-core/drm_bo.c | 14 ++-- linux-core/drm_bo_lock.c | 4 +- linux-core/drm_drv.c | 57 ++++++++--------- linux-core/drm_fence.c | 4 +- linux-core/drm_fops.c | 39 ++++++------ linux-core/drm_object.c | 16 ++--- linux-core/drm_proc.c | 67 ++++++++++++-------- linux-core/drm_stub.c | 151 ++++++++++++++++++++++++++++---------------- linux-core/drm_sysfs.c | 46 ++++++++------ linux-core/drm_vm.c | 20 +++--- linux-core/i810_dma.c | 4 +- shared-core/i915_dma.c | 4 +- 14 files changed, 263 insertions(+), 207 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index f196e11d..1fea807b 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -408,13 +408,12 @@ enum drm_ref_type { struct drm_file { int authenticated; int master; - int minor; pid_t pid; uid_t uid; drm_magic_t magic; unsigned long ioctl_count; struct list_head lhead; - struct drm_head *head; + struct drm_minor *minor; int remove_auth_on_close; unsigned long lock_count; @@ -721,16 +720,19 @@ struct drm_driver { struct pci_driver pci_driver; }; +#define DRM_MINOR_UNASSIGNED 0 +#define DRM_MINOR_LEGACY 1 + /** - * DRM head structure. This structure represent a video head on a card - * that may contain multiple heads. Embed one per head of these in the - * private drm_device structure. + * DRM minor structure. This structure represents a drm minor number. */ -struct drm_head { - int minor; /**< Minor device number */ +struct drm_minor { + int index; /**< Minor device number */ + int type; /**< Control or render */ + dev_t device; /**< Device number for mknod */ + struct device kdev; /**< Linux device */ struct drm_device *dev; struct proc_dir_entry *dev_root; /**< proc directory entry */ - dev_t device; /**< Device number for mknod */ struct class_device *dev_class; }; @@ -740,7 +742,6 @@ struct drm_head { * may contain multiple heads. */ struct drm_device { - struct device dev; /**< Linux device */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ char *devname; /**< For /proc/interrupts */ @@ -870,7 +871,7 @@ struct drm_device { struct drm_driver *driver; drm_local_map_t *agp_buffer_map; unsigned int agp_buffer_token; - struct drm_head primary; /**< primary screen head */ + struct drm_minor *primary; /**< render type primary screen head */ struct drm_fence_manager fm; struct drm_buffer_manager bm; @@ -1187,23 +1188,20 @@ extern void drm_agp_chipset_flush(struct drm_device *dev); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); -extern int drm_put_head(struct drm_head * head); +extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; /* 1 to enable debug output */ -extern unsigned int drm_cards_limit; -extern struct drm_head **drm_heads; + extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; +extern struct idr drm_minors_idr; + extern drm_local_map_t *drm_getsarea(struct drm_device *dev); /* Proc support (drm_proc.h) */ -extern int drm_proc_init(struct drm_device *dev, - int minor, - struct proc_dir_entry *root, - struct proc_dir_entry **dev_root); -extern int drm_proc_cleanup(int minor, - struct proc_dir_entry *root, - struct proc_dir_entry *dev_root); +int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root); +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root); /* Scatter Gather Support (drm_scatter.h) */ extern void drm_sg_cleanup(struct drm_sg_mem * entry); @@ -1226,8 +1224,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah); struct drm_sysfs_class; extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); -extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head); -extern void drm_sysfs_device_remove(struct drm_device *dev); +extern int drm_sysfs_device_add(struct drm_minor *minor); +extern void drm_sysfs_device_remove(struct drm_minor *minor); /* * Basic memory manager support (drm_mm.c) diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index f58d5516..0aa94a75 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -130,7 +130,7 @@ EXPORT_SYMBOL(drm_agp_acquire); int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return drm_agp_acquire((struct drm_device *) file_priv->head->dev); + return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); } /** diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 17180d8d..95802fe2 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1190,7 +1190,7 @@ static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle, struct drm_bo_info_rep *rep) { struct drm_buffer_object *bo; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int ret = 0; int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; @@ -1262,7 +1262,7 @@ out: static int drm_buffer_object_unmap(struct drm_file *file_priv, uint32_t handle) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_buffer_object *bo; struct drm_ref_object *ro; int ret = 0; @@ -1654,7 +1654,7 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, struct drm_bo_info_rep *rep, struct drm_buffer_object **bo_rep) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_buffer_object *bo; int ret; @@ -1690,7 +1690,7 @@ EXPORT_SYMBOL(drm_bo_handle_validate); static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle, struct drm_bo_info_rep *rep) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_buffer_object *bo; mutex_lock(&dev->struct_mutex); @@ -1713,7 +1713,7 @@ static int drm_bo_handle_wait(struct drm_file *file_priv, uint32_t handle, uint32_t hint, struct drm_bo_info_rep *rep) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_buffer_object *bo; int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; int ret; @@ -1833,7 +1833,7 @@ EXPORT_SYMBOL(drm_buffer_object_create); static int drm_bo_add_user_object(struct drm_file *file_priv, struct drm_buffer_object *bo, int shareable) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -1881,7 +1881,7 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil if (bo_type == drm_bo_type_user) req->flags &= ~DRM_BO_FLAG_SHAREABLE; - ret = drm_buffer_object_create(file_priv->head->dev, + ret = drm_buffer_object_create(file_priv->minor->dev, req->size, bo_type, req->flags, req->hint, req->page_alignment, req->buffer_start, &entry); diff --git a/linux-core/drm_bo_lock.c b/linux-core/drm_bo_lock.c index f967fb7c..2795384e 100644 --- a/linux-core/drm_bo_lock.c +++ b/linux-core/drm_bo_lock.c @@ -141,7 +141,7 @@ int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv) * while holding it. */ - dev = file_priv->head->dev; + dev = file_priv->minor->dev; mutex_lock(&dev->struct_mutex); ret = drm_add_user_object(file_priv, &lock->base, 0); lock->base.remove = &drm_bo_write_lock_remove; @@ -156,7 +156,7 @@ int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv) int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_ref_object *ro; mutex_lock(&dev->struct_mutex); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 3c2794d0..1daa8653 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -416,35 +416,35 @@ static void drm_cleanup(struct drm_device * dev) drm_mm_takedown(&dev->offset_manager); drm_ht_remove(&dev->object_hash); - drm_put_head(&dev->primary); + drm_put_minor(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } -void drm_exit(struct drm_driver *driver) +int drm_minors_cleanup(int id, void *ptr, void *data) { - int i; - struct drm_device *dev = NULL; - struct drm_head *head; + struct drm_minor *minor = ptr; + struct drm_device *dev; + struct drm_driver *driver = data; + + dev = minor->dev; + if (minor->dev->driver != driver) + return 0; + + if (minor->type != DRM_MINOR_LEGACY) + return 0; + if (dev) + pci_dev_put(dev->pdev); + drm_cleanup(dev); + return 1; +} + +void drm_exit(struct drm_driver *driver) +{ DRM_DEBUG("\n"); if (drm_fb_loaded) { - for (i = 0; i < drm_cards_limit; i++) { - head = drm_heads[i]; - if (!head) - continue; - if (!head->dev) - continue; - if (head->dev->driver != driver) - continue; - dev = head->dev; - if (dev) { - /* release the pci driver */ - if (dev->pdev) - pci_dev_put(dev->pdev); - drm_cleanup(dev); - } - } + idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); } else pci_unregister_driver(&driver->pci_driver); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) @@ -467,6 +467,7 @@ static int __init drm_core_init(void) unsigned long avail_memctl_mem; unsigned long max_memctl_mem; + idr_init(&drm_minors_idr); si_meminfo(&si); /* @@ -488,11 +489,6 @@ static int __init drm_core_init(void) drm_init_memctl(avail_memctl_mem/2, avail_memctl_mem*3/4, si.mem_unit); ret = -ENOMEM; - drm_cards_limit = - (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1); - drm_heads = drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB); - if (!drm_heads) - goto err_p1; if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) goto err_p1; @@ -521,7 +517,8 @@ err_p3: drm_sysfs_destroy(); err_p2: unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + + idr_destroy(&drm_minors_idr); err_p1: return ret; } @@ -533,7 +530,7 @@ static void __exit drm_core_exit(void) unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + idr_destroy(&drm_minors_idr); } module_init(drm_core_init); @@ -593,7 +590,7 @@ EXPORT_SYMBOL(drm_ioctl); long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); @@ -605,7 +602,7 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++file_priv->ioctl_count; DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", - current->pid, cmd, nr, (long)old_encode_dev(file_priv->head->device), + current->pid, cmd, nr, (long)old_encode_dev(file_priv->minor->device), file_priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 247bc0a4..9d80327f 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -494,7 +494,7 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class, int drm_fence_add_user_object(struct drm_file *priv, struct drm_fence_object *fence, int shareable) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -590,7 +590,7 @@ void drm_fence_manager_takedown(struct drm_device *dev) struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv, uint32_t handle) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_user_object *uo; struct drm_fence_object *fence; diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 0e1c486c..7fe274a2 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -128,16 +128,15 @@ static int drm_setup(struct drm_device * dev) int drm_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + int minor_id = iminor(inode); + struct drm_minor *minor; int retcode = 0; - if (!((minor >= 0) && (minor < drm_cards_limit))) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - if (!drm_heads[minor]) - return -ENODEV; - - if (!(dev = drm_heads[minor]->dev)) + if (!(dev = minor->dev)) return -ENODEV; retcode = drm_open_helper(inode, filp, dev); @@ -176,19 +175,18 @@ EXPORT_SYMBOL(drm_open); int drm_stub_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + struct drm_minor *minor; + int minor_id = iminor(inode); int err = -ENODEV; const struct file_operations *old_fops; DRM_DEBUG("\n"); - if (!((minor >= 0) && (minor < drm_cards_limit))) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - - if (!drm_heads[minor]) - return -ENODEV; - - if (!(dev = drm_heads[minor]->dev)) + + if (!(dev = minor->dev)) return -ENODEV; old_fops = filp->f_op; @@ -233,7 +231,7 @@ static int drm_cpu_valid(void) static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev) { - int minor = iminor(inode); + int minor_id = iminor(inode); struct drm_file *priv; int ret; int i, j; @@ -243,7 +241,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (!drm_cpu_valid()) return -EINVAL; - DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor); + DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor_id); priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); if (!priv) @@ -254,8 +252,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->filp = filp; priv->uid = current->euid; priv->pid = current->pid; - priv->minor = minor; - priv->head = drm_heads[minor]; + priv->minor = idr_find(&drm_minors_idr, minor_id); priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); @@ -320,11 +317,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp, int drm_fasync(int fd, struct file *filp, int on) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int retcode; DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, - (long)old_encode_dev(priv->head->device)); + (long)old_encode_dev(priv->minor->device)); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; @@ -374,7 +371,7 @@ static void drm_object_release(struct file *filp) int drm_release(struct inode *inode, struct file *filp) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int retcode = 0; lock_kernel(); @@ -389,7 +386,7 @@ int drm_release(struct inode *inode, struct file *filp) */ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", - current->pid, (long)old_encode_dev(file_priv->head->device), + current->pid, (long)old_encode_dev(file_priv->minor->device), dev->open_count); if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c index 7d2e3a2b..2994b716 100644 --- a/linux-core/drm_object.c +++ b/linux-core/drm_object.c @@ -33,7 +33,7 @@ int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item, int shareable) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; DRM_ASSERT_LOCKED(&dev->struct_mutex); @@ -58,7 +58,7 @@ EXPORT_SYMBOL(drm_add_user_object); struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, uint32_t key) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_hash_item *hash; int ret; struct drm_user_object *item; @@ -85,7 +85,7 @@ EXPORT_SYMBOL(drm_lookup_user_object); static void drm_deref_user_object(struct drm_file *priv, struct drm_user_object *item) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; if (atomic_dec_and_test(&item->refcount)) { @@ -121,7 +121,7 @@ int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced struct drm_ref_object *item; struct drm_open_hash *ht = &priv->refd_object_hash[ref_action]; - DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex); + DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); if (!referenced_object->shareable && priv != referenced_object->owner) { DRM_ERROR("Not allowed to reference this object\n"); return -EINVAL; @@ -178,7 +178,7 @@ struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv, struct drm_hash_item *hash; int ret; - DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex); + DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); ret = drm_ht_find_item(&priv->refd_object_hash[ref_action], (unsigned long)referenced_object, &hash); if (ret) @@ -212,7 +212,7 @@ void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item) struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action]; enum drm_ref_type unref_action; - DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex); + DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex); unref_action = item->unref_action; if (atomic_dec_and_test(&item->refcount)) { ret = drm_ht_remove_item(ht, &item->hash); @@ -239,7 +239,7 @@ EXPORT_SYMBOL(drm_remove_ref_object); int drm_user_object_ref(struct drm_file *priv, uint32_t user_token, enum drm_object_type type, struct drm_user_object **object) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_user_object *uo; struct drm_hash_item *hash; int ret; @@ -269,7 +269,7 @@ out_err: int drm_user_object_unref(struct drm_file *priv, uint32_t user_token, enum drm_object_type type) { - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_user_object *uo; struct drm_ref_object *ro; int ret; diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c index 3012c5b0..67afee8e 100644 --- a/linux-core/drm_proc.c +++ b/linux-core/drm_proc.c @@ -90,34 +90,35 @@ static struct drm_proc_list { * "/proc/dri/%minor%/", and each entry in proc_list as * "/proc/dri/%minor%/%name%". */ -int drm_proc_init(struct drm_device * dev, int minor, - struct proc_dir_entry *root, struct proc_dir_entry **dev_root) +int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root) { struct proc_dir_entry *ent; int i, j; char name[64]; - sprintf(name, "%d", minor); - *dev_root = proc_mkdir(name, root); - if (!*dev_root) { + sprintf(name, "%d", minor_id); + minor->dev_root = proc_mkdir(name, root); + if (!minor->dev_root) { DRM_ERROR("Cannot create /proc/dri/%s\n", name); return -1; } for (i = 0; i < DRM_PROC_ENTRIES; i++) { ent = create_proc_entry(drm_proc_list[i].name, - S_IFREG | S_IRUGO, *dev_root); + S_IFREG | S_IRUGO, minor->dev_root); if (!ent) { DRM_ERROR("Cannot create /proc/dri/%s/%s\n", name, drm_proc_list[i].name); for (j = 0; j < i; j++) remove_proc_entry(drm_proc_list[i].name, - *dev_root); + minor->dev_root); remove_proc_entry(name, root); + minor->dev_root = NULL; return -1; } ent->read_proc = drm_proc_list[i].f; - ent->data = dev; + ent->data = minor; } return 0; } @@ -132,18 +133,17 @@ int drm_proc_init(struct drm_device * dev, int minor, * * Remove all proc entries created by proc_init(). */ -int drm_proc_cleanup(int minor, struct proc_dir_entry *root, - struct proc_dir_entry *dev_root) +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) { int i; char name[64]; - if (!root || !dev_root) + if (!root || !minor->dev_root) return 0; for (i = 0; i < DRM_PROC_ENTRIES; i++) - remove_proc_entry(drm_proc_list[i].name, dev_root); - sprintf(name, "%d", minor); + remove_proc_entry(drm_proc_list[i].name, minor->dev_root); + sprintf(name, "%d", minor->index); remove_proc_entry(name, root); return 0; @@ -165,7 +165,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root, static int drm_name_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; if (offset > DRM_PROC_LIMIT) { @@ -207,7 +208,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request, static int drm__vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_map *map; struct drm_map_list *r_list; @@ -264,7 +266,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, static int drm_vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -287,7 +290,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request, static int drm__queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; int i; struct drm_queue *q; @@ -337,7 +341,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset, static int drm_queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -360,7 +365,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, static int drm__bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_device_dma *dma = dev->dma; int i; @@ -409,7 +415,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request, static int drm_bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -432,7 +439,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, static int drm__objects_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_buffer_manager *bm = &dev->bm; struct drm_fence_manager *fm = &dev->fm; @@ -496,7 +504,8 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request, static int drm_objects_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -519,7 +528,8 @@ static int drm_objects_info(char *buf, char **start, off_t offset, int request, static int drm__clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_file *priv; @@ -535,7 +545,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset, list_for_each_entry(priv, &dev->filelist, lhead) { DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", priv->authenticated ? 'y' : 'n', - priv->minor, + priv->minor->index, priv->pid, priv->uid, priv->magic, priv->ioctl_count); } @@ -552,7 +562,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset, static int drm_clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -566,7 +577,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset, static int drm__vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_vma_entry *pt; struct vm_area_struct *vma; @@ -625,7 +637,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, static int drm_vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 00a24521..6584f51d 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -37,23 +37,49 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_cards_limit = 16; /* Enough for one machine */ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); -MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); MODULE_PARM_DESC(debug, "Enable debug output"); -module_param_named(cards_limit, drm_cards_limit, int, 0444); module_param_named(debug, drm_debug, int, 0600); -struct drm_head **drm_heads; +struct idr drm_minors_idr; + struct class *drm_class; struct proc_dir_entry *drm_proc_root; +static int drm_minor_get_id(struct drm_device *dev, int type) +{ + int new_id; + int ret; + int base = 0, limit = 63; + +again: + if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Out of memory expanding drawable idr\n"); + return -ENOMEM; + } + mutex_lock(&dev->struct_mutex); + ret = idr_get_new_above(&drm_minors_idr, NULL, + base, &new_id); + mutex_unlock(&dev->struct_mutex); + if (ret == -EAGAIN) { + goto again; + } else if (ret) { + return ret; + } + + if (new_id >= limit) { + idr_remove(&drm_minors_idr, new_id); + return -EINVAL; + } + return new_id; +} + static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -161,49 +187,60 @@ error_out_unreg: * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_head(struct drm_device * dev, struct drm_head * head) +static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) { - struct drm_head **heads = drm_heads; + struct drm_minor *new_minor; int ret; - int minor; + int minor_id; DRM_DEBUG("\n"); - for (minor = 0; minor < drm_cards_limit; minor++, heads++) { - if (!*heads) { - - *head = (struct drm_head) { - .dev = dev, - .device = MKDEV(DRM_MAJOR, minor), - .minor = minor, - }; - if ((ret = - drm_proc_init(dev, minor, drm_proc_root, - &head->dev_root))) { - printk(KERN_ERR - "DRM: Failed to initialize /proc/dri.\n"); - goto err_g1; - } - - ret = drm_sysfs_device_add(dev, head); - if (ret) { - printk(KERN_ERR - "DRM: Error sysfs_device_add.\n"); - goto err_g2; - } - *heads = head; - - DRM_DEBUG("new minor assigned %d\n", minor); - return 0; + minor_id = drm_minor_get_id(dev, type); + if (minor_id < 0) + return minor_id; + + new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); + if (!new_minor) { + ret = -ENOMEM; + goto err_idr; + } + + new_minor->type = type; + new_minor->device = MKDEV(DRM_MAJOR, minor_id); + new_minor->dev = dev; + new_minor->index = minor_id; + + idr_replace(&drm_minors_idr, new_minor, minor_id); + + if (type == DRM_MINOR_LEGACY) { + ret = drm_proc_init(new_minor, minor_id, drm_proc_root); + if (ret) { + DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); + goto err_mem; } + } else + new_minor->dev_root = NULL; + + ret = drm_sysfs_device_add(new_minor); + if (ret) { + printk(KERN_ERR + "DRM: Error sysfs_device_add.\n"); + goto err_g2; } - DRM_ERROR("out of minors\n"); - return -ENOMEM; + *minor = new_minor; + + DRM_DEBUG("new minor assigned %d\n", minor_id); + return 0; + + err_g2: - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); -err_g1: - *head = (struct drm_head) { - .dev = NULL}; + if (new_minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(new_minor, drm_proc_root); +err_mem: + kfree(new_minor); +err_idr: + idr_remove(&drm_minors_idr, minor_id); + *minor = NULL; return ret; } @@ -246,22 +283,29 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, printk(KERN_ERR "DRM: fill_in_dev failed\n"); goto err_g3; } - if ((ret = drm_get_head(dev, &dev->primary))) + + /* only add the control node on a modesetting platform */ + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g3; + if (dev->driver->load) + if ((ret = dev->driver->load(dev, ent->driver_data))) + goto err_g4; + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, - driver->date, dev->primary.minor); + driver->date, dev->primary->index); return 0; - - err_g3: +err_g4: + drm_put_minor(&dev->primary); +err_g3: if (!drm_fb_loaded) pci_disable_device(pdev); - err_g2: +err_g2: if (!drm_fb_loaded) pci_release_regions(pdev); - err_g1: +err_g1: if (!drm_fb_loaded) pci_set_drvdata(pdev, NULL); @@ -310,17 +354,18 @@ int drm_put_dev(struct drm_device * dev) * last minor released. * */ -int drm_put_head(struct drm_head * head) +int drm_put_minor(struct drm_minor **minor_p) { - int minor = head->minor; - - DRM_DEBUG("release secondary minor %d\n", minor); + struct drm_minor *minor = *minor_p; + DRM_DEBUG("release secondary minor %d\n", minor->index); - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); - drm_sysfs_device_remove(head->dev); + if (minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(minor, drm_proc_root); + drm_sysfs_device_remove(minor); - *head = (struct drm_head) {.dev = NULL}; + idr_remove(&drm_minors_idr, minor->index); - drm_heads[minor] = NULL; + kfree(minor); + *minor_p = NULL; return 0; } diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c index c02e2049..32759424 100644 --- a/linux-core/drm_sysfs.c +++ b/linux-core/drm_sysfs.c @@ -19,7 +19,7 @@ #include "drm_core.h" #include "drmP.h" -#define to_drm_device(d) container_of(d, struct drm_device, dev) +#define to_drm_minor(d) container_of(d, struct drm_minor, kdev) /** * drm_sysfs_suspend - DRM class suspend hook @@ -31,7 +31,8 @@ */ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; printk(KERN_ERR "%s\n", __FUNCTION__); @@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) */ static int drm_sysfs_resume(struct device *dev) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; if (drm_dev->driver->resume) return drm_dev->driver->resume(drm_dev); @@ -122,10 +124,11 @@ void drm_sysfs_destroy(void) static ssize_t show_dri(struct device *device, struct device_attribute *attr, char *buf) { - struct drm_device *dev = to_drm_device(device); - if (dev->driver->dri_library_name) - return dev->driver->dri_library_name(dev, buf); - return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); + struct drm_minor *drm_minor = to_drm_minor(device); + struct drm_device *drm_dev = drm_minor->dev; + if (drm_dev->driver->dri_library_name) + return drm_dev->driver->dri_library_name(drm_dev, buf); + return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); } static struct device_attribute device_attrs[] = { @@ -154,25 +157,28 @@ static void drm_sysfs_device_release(struct device *dev) * as the parent for the Linux device, and make sure it has a file containing * the driver we're using (for userspace compatibility). */ -int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) +int drm_sysfs_device_add(struct drm_minor *minor) { int err; int i, j; + char *minor_str; - dev->dev.parent = &dev->pdev->dev; - dev->dev.class = drm_class; - dev->dev.release = drm_sysfs_device_release; - dev->dev.devt = head->device; - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); + minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.class = drm_class; + minor->kdev.release = drm_sysfs_device_release; + minor->kdev.devt = minor->device; + minor_str = "card%d"; + + snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); - err = device_register(&dev->dev); + err = device_register(&minor->kdev); if (err) { DRM_ERROR("device add failed: %d\n", err); goto err_out; } for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - err = device_create_file(&dev->dev, &device_attrs[i]); + err = device_create_file(&minor->kdev, &device_attrs[i]); if (err) goto err_out_files; } @@ -182,8 +188,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) err_out_files: if (i > 0) for (j = 0; j < i; j++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); err_out: return err; @@ -196,11 +202,11 @@ err_out: * This call unregisters and cleans up a class device that was created with a * call to drm_sysfs_device_add() */ -void drm_sysfs_device_remove(struct drm_device *dev) +void drm_sysfs_device_remove(struct drm_minor *minor) { int i; for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); } diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index c481a530..15e1c0f5 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -86,7 +86,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, unsigned long address) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; struct drm_map_list *r_list; struct drm_hash_item *hash; @@ -204,7 +204,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, static void drm_vm_shm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; struct drm_map *map; struct drm_map_list *r_list; @@ -286,7 +286,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, unsigned long address) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_device_dma *dma = dev->dma; unsigned long offset; unsigned long page_nr; @@ -323,7 +323,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, { struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_sg_mem *entry = dev->sg; unsigned long offset; unsigned long map_offset; @@ -419,7 +419,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { static void drm_vm_open_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *vma_entry; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -437,7 +437,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma) static void drm_vm_open(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; mutex_lock(&dev->struct_mutex); drm_vm_open_locked(vma); @@ -455,7 +455,7 @@ static void drm_vm_open(struct vm_area_struct *vma) static void drm_vm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -491,7 +491,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) struct drm_device_dma *dma; unsigned long length = vma->vm_end - vma->vm_start; - dev = priv->head->dev; + dev = priv->minor->dev; dma = dev->dma; DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", vma->vm_start, vma->vm_end, vma->vm_pgoff); @@ -556,7 +556,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; unsigned long offset = 0; struct drm_hash_item *hash; @@ -677,7 +677,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) int drm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index 3c9ca3b2..f2bf5d9d 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -113,7 +113,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) drm_i810_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->head->dev; + dev = priv->minor->dev; dev_priv = dev->dev_private; buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; @@ -141,7 +141,7 @@ static const struct file_operations i810_buffer_fops = { static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 9e474bc6..7d247f9c 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -988,7 +988,7 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, struct drm_i915_validate_buffer *buffers, uint32_t buf_count) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct i915_relocatee_info relocatee; int ret = 0; int b; @@ -1195,7 +1195,7 @@ void i915_fence_or_sync(struct drm_file *file_priv, struct drm_fence_arg *fence_arg, struct drm_fence_object **fence_p) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int ret; struct drm_fence_object *fence; -- cgit v1.2.3 From 180c9188f4cb7163f1e3e7d5098eaabf29a98540 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 20 Feb 2008 13:27:10 +1000 Subject: drm/ttm: add ioctl to get back memory managed area sized taken from modesetting branch but could be useful outside it. --- libdrm/xf86drm.c | 15 +++++++++++++++ libdrm/xf86mm.h | 1 + linux-core/drm_bo.c | 37 +++++++++++++++++++++++++++++++++++++ linux-core/drm_drv.c | 2 ++ linux-core/drm_objects.h | 2 ++ shared-core/drm.h | 6 ++++++ 6 files changed, 63 insertions(+) diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index fb8f1c66..3317ba5c 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2871,6 +2871,21 @@ int drmMMUnlock(int fd, unsigned memType, int unlockBM) return drmIoctlTimeout(fd, DRM_IOCTL_MM_UNLOCK, &arg); } +int drmMMInfo(int fd, unsigned memType, uint64_t *size) +{ + struct drm_mm_info_arg arg; + + memset(&arg, 0, sizeof(arg)); + + arg.mem_type = memType; + + if (ioctl(fd, DRM_IOCTL_MM_INFO, &arg)) + return -errno; + + *size = arg.p_size; + return 0; +} + int drmBOVersion(int fd, unsigned int *major, unsigned int *minor, unsigned int *patchlevel) diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h index c80288a7..bb573407 100644 --- a/libdrm/xf86mm.h +++ b/libdrm/xf86mm.h @@ -172,6 +172,7 @@ extern int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, extern int drmMMTakedown(int fd, unsigned memType); extern int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict); extern int drmMMUnlock(int fd, unsigned memType, int unlockBM); +extern int drmMMInfo(int fd, unsigned memType, uint64_t *size); extern int drmBOSetStatus(int fd, drmBO *buf, uint64_t flags, uint64_t mask, unsigned int hint, diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 95802fe2..b67946eb 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -2283,6 +2283,7 @@ int drm_bo_init_mm(struct drm_device *dev, } man->has_type = 1; man->use_type = 1; + man->size = p_size; INIT_LIST_HEAD(&man->lru); INIT_LIST_HEAD(&man->pinned); @@ -2553,6 +2554,42 @@ int drm_mm_unlock_ioctl(struct drm_device *dev, return 0; } +int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_mm_info_arg *arg = data; + struct drm_buffer_manager *bm = &dev->bm; + struct drm_bo_driver *driver = dev->driver->bo_driver; + struct drm_mem_type_manager *man; + int ret = 0; + int mem_type = arg->mem_type; + + if (!driver) { + DRM_ERROR("Buffer objects are not supported by this driver\n"); + return -EINVAL; + } + + if (mem_type >= DRM_BO_MEM_TYPES) { + DRM_ERROR("Illegal memory type %d\n", arg->mem_type); + return -EINVAL; + } + + mutex_lock(&dev->struct_mutex); + if (!bm->initialized) { + DRM_ERROR("DRM memory manager was not initialized\n"); + ret = -EINVAL; + goto out; + } + + + man = &bm->man[arg->mem_type]; + + arg->p_size = man->size; + +out: + mutex_unlock(&dev->struct_mutex); + + return ret; +} /* * buffer object vm functions. */ diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 1daa8653..b8b8333e 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -148,6 +148,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0), + + DRM_IOCTL_DEF(DRM_IOCTL_MM_INFO, drm_mm_info_ioctl, 0), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index fd32f0f4..ae0725c1 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -525,6 +525,7 @@ struct drm_mem_type_manager { unsigned long io_offset; unsigned long io_size; void *io_addr; + uint64_t size; /* size of managed area for reporting to userspace */ }; struct drm_bo_lock { @@ -651,6 +652,7 @@ extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_driver_finish(struct drm_device *dev); extern int drm_bo_driver_init(struct drm_device *dev); diff --git a/shared-core/drm.h b/shared-core/drm.h index 663696c1..5981dcb8 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -955,6 +955,11 @@ struct drm_mm_init_arg { uint64_t p_size; }; +struct drm_mm_info_arg { + unsigned int mem_type; + uint64_t p_size; +}; + /** * \name Ioctls Definitions */ @@ -1046,6 +1051,7 @@ struct drm_mm_init_arg { #define DRM_IOCTL_BO_INFO DRM_IOWR(0xd4, struct drm_bo_reference_info_arg) #define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg) #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) +#define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) /*@}*/ -- cgit v1.2.3 From d5c0101252e9f48ef1b59f48c05fea7007df97f0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 18 Feb 2008 10:39:21 +1000 Subject: ttm: make sure userspace can't destroy kernel create memory managers this adds something to say the kernel initialised the memory region not the userspace. and blocks userspace from deallocating kernel areas --- linux-core/drm_bo.c | 30 ++++++++++++++++++++---------- linux-core/drm_objects.h | 6 ++++-- shared-core/nouveau_mem.c | 6 +++--- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index b67946eb..3e8ffa0f 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -2180,7 +2180,7 @@ restart: return 0; } -int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type) +int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_clean) { struct drm_buffer_manager *bm = &dev->bm; struct drm_mem_type_manager *man = &bm->man[mem_type]; @@ -2196,6 +2196,13 @@ int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type) "memory manager type %u\n", mem_type); return ret; } + + if ((man->kern_init_type) && (kern_clean == 0)) { + DRM_ERROR("Trying to take down kernel initialized " + "memory manager type %u\n", mem_type); + return -EPERM; + } + man->use_type = 0; man->has_type = 0; @@ -2247,9 +2254,9 @@ static int drm_bo_lock_mm(struct drm_device *dev, unsigned mem_type) return ret; } -int drm_bo_init_mm(struct drm_device *dev, - unsigned type, - unsigned long p_offset, unsigned long p_size) +int drm_bo_init_mm(struct drm_device *dev, unsigned type, + unsigned long p_offset, unsigned long p_size, + int kern_init) { struct drm_buffer_manager *bm = &dev->bm; int ret = -EINVAL; @@ -2283,6 +2290,7 @@ int drm_bo_init_mm(struct drm_device *dev, } man->has_type = 1; man->use_type = 1; + man->kern_init_type = kern_init; man->size = p_size; INIT_LIST_HEAD(&man->lru); @@ -2316,7 +2324,7 @@ int drm_bo_driver_finish(struct drm_device *dev) man = &bm->man[i]; if (man->has_type) { man->use_type = 0; - if ((i != DRM_BO_MEM_LOCAL) && drm_bo_clean_mm(dev, i)) { + if ((i != DRM_BO_MEM_LOCAL) && drm_bo_clean_mm(dev, i, 1)) { ret = -EBUSY; DRM_ERROR("DRM memory manager type %d " "is not clean.\n", i); @@ -2386,7 +2394,7 @@ int drm_bo_driver_init(struct drm_device *dev) * Initialize the system memory buffer type. * Other types need to be driver / IOCTL initialized. */ - ret = drm_bo_init_mm(dev, DRM_BO_MEM_LOCAL, 0, 0); + ret = drm_bo_init_mm(dev, DRM_BO_MEM_LOCAL, 0, 0, 1); if (ret) goto out_unlock; @@ -2446,7 +2454,7 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ goto out; } ret = drm_bo_init_mm(dev, arg->mem_type, - arg->p_offset, arg->p_size); + arg->p_offset, arg->p_size, 0); out: mutex_unlock(&dev->struct_mutex); @@ -2485,9 +2493,11 @@ int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *f goto out; } ret = 0; - if (drm_bo_clean_mm(dev, arg->mem_type)) { - DRM_ERROR("Memory manager type %d not clean. " - "Delaying takedown\n", arg->mem_type); + if ((ret = drm_bo_clean_mm(dev, arg->mem_type, 0))) { + if (ret == -EINVAL) + DRM_ERROR("Memory manager type %d not clean. " + "Delaying takedown\n", arg->mem_type); + ret = 0; } out: mutex_unlock(&dev->struct_mutex); diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index ae0725c1..69e3f67f 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -516,6 +516,7 @@ struct drm_buffer_object { struct drm_mem_type_manager { int has_type; int use_type; + int kern_init_type; struct drm_mm manager; struct list_head lru; struct list_head pinned; @@ -684,9 +685,10 @@ extern int drm_bo_mem_space(struct drm_buffer_object *bo, extern int drm_bo_move_buffer(struct drm_buffer_object *bo, uint64_t new_mem_flags, int no_wait, int move_unfenced); -extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type); +extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_clean); extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, - unsigned long p_offset, unsigned long p_size); + unsigned long p_offset, unsigned long p_size, + int kern_init); extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, uint64_t flags, uint64_t mask, uint32_t hint, uint32_t fence_class, int use_old_fence_class, diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 3d376aed..80b2990d 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -376,7 +376,7 @@ nouveau_mem_init_ttm(struct drm_device *dev) bar1_size = drm_get_resource_len(dev, 1) >> PAGE_SHIFT; if (bar1_size < vram_size) { if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0, - bar1_size, vram_size - bar1_size))) { + bar1_size, vram_size - bar1_size, 1))) { DRM_ERROR("Failed PRIV0 mm init: %d\n", ret); return ret; } @@ -387,7 +387,7 @@ nouveau_mem_init_ttm(struct drm_device *dev) #ifdef HACK_OLD_MM vram_size /= 4; #endif - if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, vram_size))) { + if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, vram_size, 1))) { DRM_ERROR("Failed VRAM mm init: %d\n", ret); return ret; } @@ -407,7 +407,7 @@ nouveau_mem_init_ttm(struct drm_device *dev) if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0, dev_priv->gart_info.aper_size >> - PAGE_SHIFT))) { + PAGE_SHIFT, 1))) { DRM_ERROR("Failed TT mm init: %d\n", ret); return ret; } -- cgit v1.2.3 From 5662934ee467c3a29f9551a40fc7b2f6ee16280a Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:50:59 +0000 Subject: Fix connector description table --- linux-core/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1a4624c8..345569b6 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -48,7 +48,8 @@ static struct drm_prop_enum_list drm_dpms_enum_list[] = { DPMSModeOff, "Off" } }; static struct drm_prop_enum_list drm_conn_enum_list[] = -{ { ConnectorVGA, "VGA" }, +{ { ConnectorUnknown, "Unknown" }, + { ConnectorVGA, "VGA" }, { ConnectorDVII, "DVI-I" }, { ConnectorDVID, "DVI-D" }, { ConnectorDVIA, "DVI-A" }, -- cgit v1.2.3 From 3ea1902be993e88c068ce67355e2b3d253d1c9f2 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:51:56 +0000 Subject: propogate failed fixups back up --- linux-core/drm_crtc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 345569b6..5f93275a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -458,12 +458,12 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, if (output->crtc != crtc) continue; - if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) { goto done; } } - if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) { goto done; } @@ -517,10 +517,16 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, // drm_crtc_set_screen_sub_pixel_order(dev); done: + if (!ret) { + crtc->mode = saved_mode; + crtc->x = saved_x; + crtc->y = saved_y; + } + if (didLock) crtc->funcs->unlock (crtc); - return true; + return ret; } EXPORT_SYMBOL(drm_crtc_set_mode); -- cgit v1.2.3 From 8bfe29d9e44690a3896406acb25ca654dfad054d Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:52:37 +0000 Subject: Use ARRAY_SIZE --- linux-core/drm_crtc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 5f93275a..dfa0987f 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -735,20 +735,20 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) "EDID", 0); dev->mode_config.dpms_property = - drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4); - + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name); dev->mode_config.connector_type_property = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, - "Connector Type", 10); + "Connector Type", ARRAY_SIZE(drm_conn_enum_list)); for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++) drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name); dev->mode_config.connector_num_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, - "Connector ID", 2); + "Connector ID", 2); dev->mode_config.connector_num_property->values[0] = 0; dev->mode_config.connector_num_property->values[1] = 20; @@ -783,7 +783,6 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) dev->mode_config.tv_bottom_margin_property->values[0] = 0; dev->mode_config.tv_bottom_margin_property->values[1] = 100; - return 0; } -- cgit v1.2.3 From 1a959a2095aef397ea14a6f6cbdf2a035ec0eb5c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:53:04 +0000 Subject: Check mode before adding to EDID --- linux-core/drm_edid.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/linux-core/drm_edid.c b/linux-core/drm_edid.c index 41aa8f5e..9762567b 100644 --- a/linux-core/drm_edid.c +++ b/linux-core/drm_edid.c @@ -223,8 +223,10 @@ static int add_established_modes(struct drm_output *output, struct edid *edid) if (est_bits & (1<standard_timings[i]); - drm_mode_probed_add(output, newmode); - modes++; + if (newmode) { + drm_mode_probed_add(output, newmode); + modes++; + } } return modes; @@ -283,11 +287,13 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid) if (timing->pixel_clock) { newmode = drm_mode_detailed(dev, timing); /* First detailed mode is preferred */ - if (i == 0 && edid->preferred_timing) - newmode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(output, newmode); + if (newmode) { + if (i == 0 && edid->preferred_timing) + newmode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(output, newmode); - modes++; + modes++; + } continue; } @@ -312,8 +318,10 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid) std = &data->data.timings[j]; newmode = drm_mode_std(dev, std); - drm_mode_probed_add(output, newmode); - modes++; + if (newmode) { + drm_mode_probed_add(output, newmode); + modes++; + } } break; default: -- cgit v1.2.3 From b87c7ff79ee88ec39a285bc17bd2996252b9fd48 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 5 Mar 2008 10:33:16 +0000 Subject: Add property info. fix bo handle --- tests/modedemo/demo.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c index 00020bde..83a33aa6 100644 --- a/tests/modedemo/demo.c +++ b/tests/modedemo/demo.c @@ -429,7 +429,7 @@ void demoUpdateRes(struct demo_driver *driver) int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out) { int count = 0; - int i; + int i,j; int fd = driver->fd; drmModeResPtr res = driver->res; @@ -441,10 +441,20 @@ int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, if (!output) continue; - if (output->connection != DRM_MODE_CONNECTED) { + if (output->connection == DRM_MODE_DISCONNECTED) { drmModeFreeOutput(output); continue; } + + for (j = 0; j < output->count_props; j++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(fd, output->props[j]); + + printf("Property: %s\n",prop->name); + if (prop->count_enums) + printf("%s\n",prop->enums[output->prop_values[j]].name); + } out[count++] = output; } @@ -483,7 +493,7 @@ drmModeFBPtr createFB(int fd, drmModeResPtr res) goto err; } - ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, bo->handle, &fb); + ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, bo.handle, &fb); if (ret) goto err_bo; -- cgit v1.2.3 From fef1c93aa87a1ccbc473749a7e42557fc90a1fca Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 5 Mar 2008 10:33:57 +0000 Subject: build fix --- linux-core/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index dfa0987f..be491908 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -420,14 +420,14 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int saved_x, saved_y; bool didLock = false; struct drm_output *output; + bool ret = true; adjusted_mode = drm_mode_duplicate(dev, mode); crtc->enabled = drm_crtc_in_use(crtc); - if (!crtc->enabled) { + if (!crtc->enabled) return true; - } didLock = crtc->funcs->lock(crtc); -- cgit v1.2.3 From 92a30dd608c2838dea97efc04e1447056f37d0b5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 6 Mar 2008 14:43:23 +1000 Subject: drm/bo: allow non-suser priv to add kernel BOs. modprobe can be run with dropped capabilities we still want the kernel bos to work. --- linux-core/drm_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 3e8ffa0f..fd3cf9db 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -970,7 +970,7 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo, return -EINVAL; } - if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { + if (bo->type != drm_bo_type_kernel && (new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { DRM_ERROR("DRM_BO_FLAG_NO_EVICT is only available to priviliged processes.\n"); return -EPERM; } -- cgit v1.2.3 From 48a166af14d7455835b9dc2ffd831347d18635d2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 08:49:27 +1000 Subject: woah somehow got these upstream --- shared-core/drm.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/shared-core/drm.h b/shared-core/drm.h index 753af6b7..6b3c6229 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1052,7 +1052,6 @@ struct drm_mm_info_arg { #define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg) #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) #define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) -<<<<<<< HEAD:shared-core/drm.h #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) @@ -1070,8 +1069,6 @@ struct drm_mm_info_arg { #define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property) #define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xAC, struct drm_mode_cursor) #define DRM_IOCTL_MODE_HOTPLUG DRM_IOWR(0xAD, struct drm_mode_hotplug) -======= ->>>>>>> d5c0101252e9f48ef1b59f48c05fea7007df97f0:shared-core/drm.h /*@}*/ -- cgit v1.2.3 From add7d21c79e2bd2012d92bb0043023230ec9aa74 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 08:56:20 +1000 Subject: drm: fixup for new sysfs API --- libdrm/xf86drmMode.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 07b14dbf..f86cc48f 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -568,6 +568,25 @@ int drmCheckModesettingSupported(const char *busid) if (ret != 4) return -EINVAL; + sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", + domain, bus, dev, func); + + sysdir = opendir(pci_dev_dir); + if (sysdir) { + dent = readdir(sysdir); + while (dent) { + if (!strncmp(dent->d_name, "controlD", 8)) { + found = 1; + break; + } + + dent = readdir(sysdir); + } + closedir(sysdir); + if (found) + return 0; + } + sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", domain, bus, dev, func); -- cgit v1.2.3 From ccae12a837e7b17c4e9211295ecbd18807020742 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 08:58:24 +1000 Subject: I really screwed up that merge somehow --- shared-core/drm.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/shared-core/drm.h b/shared-core/drm.h index 6b3c6229..303a84b6 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -960,6 +960,175 @@ struct drm_mm_info_arg { uint64_t p_size; }; + +/* + * Drm mode setting + */ +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_OUTPUT_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +struct drm_mode_modeinfo { + unsigned int clock; + unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew; + unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan; + + unsigned int vrefresh; /* vertical refresh * 1000 */ + + unsigned int flags; + unsigned int type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + uint64_t fb_id_ptr; + uint64_t crtc_id_ptr; + uint64_t output_id_ptr; + int count_fbs; + int count_crtcs; + int count_outputs; + int min_width, max_width; + int min_height, max_height; +}; + +struct drm_mode_crtc { + uint64_t set_outputs_ptr; + + unsigned int crtc_id; /**< Id */ + unsigned int fb_id; /**< Id of framebuffer */ + + int x, y; /**< Position on the frameuffer */ + + int count_outputs; + unsigned int outputs; /**< Outputs that are connected */ + + int count_possibles; + unsigned int possibles; /**< Outputs that can be connected */ + int gamma_size; + int mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_OUTPUT_NONE 0 +#define DRM_MODE_OUTPUT_DAC 1 +#define DRM_MODE_OUTPUT_TMDS 2 +#define DRM_MODE_OUTPUT_LVDS 3 +#define DRM_MODE_OUTPUT_TVDAC 4 + +struct drm_mode_get_output { + + uint64_t modes_ptr; + uint64_t props_ptr; + uint64_t prop_values_ptr; + + int count_modes; + int count_props; + unsigned int output; /**< Id */ + unsigned int crtc; /**< Id of crtc */ + unsigned int output_type; + unsigned int output_type_id; + + unsigned int connection; + unsigned int mm_width, mm_height; /**< HxW in millimeters */ + unsigned int subpixel; + int count_crtcs; + int count_clones; + unsigned int crtcs; /**< possible crtc to connect to */ + unsigned int clones; /**< list of clones */ +}; + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) // enumerated type with text strings +#define DRM_MODE_PROP_BLOB (1<<4) + +struct drm_mode_property_enum { + uint64_t value; + unsigned char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + uint64_t values_ptr; /* values and blob lengths */ + uint64_t enum_blob_ptr; /* enum and blob id ptrs */ + + unsigned int prop_id; + unsigned int flags; + unsigned char name[DRM_PROP_NAME_LEN]; + + int count_values; + int count_enum_blobs; +}; + +struct drm_mode_output_set_property { + uint64_t value; + unsigned int prop_id; + unsigned int output_id; +}; + +struct drm_mode_get_blob { + uint32_t blob_id; + uint32_t length; + uint64_t data; +}; + +struct drm_mode_fb_cmd { + unsigned int buffer_id; + unsigned int width, height; + unsigned int pitch; + unsigned int bpp; + unsigned int handle; + unsigned int depth; +}; + +struct drm_mode_mode_cmd { + unsigned int output_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 + +/* + * depending on the value in flags diffrent members are used. + * + * CURSOR_BO uses + * crtc + * width + * height + * handle - if 0 turns the cursor of + * + * CURSOR_MOVE uses + * crtc + * x + * y + */ +struct drm_mode_cursor { + unsigned int flags; + unsigned int crtc; + int x; + int y; + uint32_t width; + uint32_t height; + unsigned int handle; +}; + +/* + * oh so ugly hotplug + */ +struct drm_mode_hotplug { + uint32_t counter; +}; + /** * \name Ioctls Definitions */ -- cgit v1.2.3 From 2540ea7dc6c0c4f0ebca3370d6ec7359e4276e13 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 09:29:35 +1000 Subject: flush_agp_mappings commit --- linux-core/drm_compat.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 136a7296..8f2d9a94 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -333,4 +333,9 @@ typedef _Bool bool; extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t protection); #endif + +#if !defined(flush_agp_mappings) +#define flush_agp_mappings() do {} while(0) +#endif + #endif -- cgit v1.2.3 From 47b7ec71fefc2574293c48172c563f549c31f87a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 12:15:38 +1100 Subject: drm/modesetting: fixup irq removal on exit --- linux-core/drm_irq.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 7dddbe19..6b740b18 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -261,9 +261,6 @@ int drm_irq_uninstall(struct drm_device * dev) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return 0; - mutex_lock(&dev->struct_mutex); irq_enabled = dev->irq_enabled; dev->irq_enabled = 0; @@ -318,6 +315,8 @@ int drm_control(struct drm_device *dev, void *data, case DRM_UNINST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; return drm_irq_uninstall(dev); default: return -EINVAL; -- cgit v1.2.3 From 348d95e00be73b650dabcf121e6b18d669bf4192 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 12:25:26 +1100 Subject: worst merge effort ever --- linux-core/drm_stub.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index ba13e5e5..6856075b 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -355,10 +355,6 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if ((ret = dev->driver->load(dev, ent->driver_data))) goto err_g5; - if (dev->driver->load) - if ((ret = dev->driver->load(dev, ent->driver_data))) - goto err_g4; - DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); -- cgit v1.2.3 From cf28ca4212662c3c7e4bfbe51aee307ac539fb3d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 13:03:32 +1100 Subject: actually turn the irq off --- shared-core/i915_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 1f22d171..3d8a1dca 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -271,6 +271,7 @@ int i915_driver_unload(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { + drm_irq_uninstall(dev); intel_modeset_cleanup(dev); } -- cgit v1.2.3 From 33cb42a9f7c7c4f4dd91756af55de7352944efa4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 13:03:42 +1100 Subject: make startup of Xorg smoother if the mode doesn't change. just flip the framebuffer in when required. --- linux-core/drm_crtc.c | 10 ++++++++-- linux-core/intel_fb.c | 29 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index be491908..e0c85cef 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1110,13 +1110,17 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ if (crtc->fb != fb) - changed = true; + flip_or_move = true; if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) flip_or_move = true; - if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) + if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) { + DRM_DEBUG("modes are different\n"); + drm_mode_debug_printmodeline(dev, &crtc->mode); + drm_mode_debug_printmodeline(dev, new_mode); changed = true; + } list_for_each_entry(output, &dev->mode_config.output_list, head) { save_crtcs[count++] = output->crtc; @@ -1161,6 +1165,8 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } drm_disable_unused_functions(dev); } else if (flip_or_move) { + if (crtc->fb != fb) + crtc->fb = fb; crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); } diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index e33494c6..931bc1b6 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -228,6 +228,7 @@ static int intelfb_set_par(struct fb_info *info) struct drm_output *output = NULL; struct fb_var_screeninfo *var = &info->var; int found = 0; + int changed = 0; DRM_DEBUG("\n"); @@ -310,11 +311,22 @@ static int intelfb_set_par(struct fb_info *info) } /* re-attach fb */ - if (!par->crtc->fb) + if (!par->crtc->fb) { par->crtc->fb = par->fb; + changed = 1; + } - if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) - return -EINVAL; + if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset) + changed = 1; + + drm_mode_debug_printmodeline(dev, drm_mode); + drm_mode_debug_printmodeline(dev, &par->crtc->mode); + if (!drm_mode_equal(drm_mode, &par->crtc->mode)) + changed = 1; + + if (changed) + if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) + return -EINVAL; return 0; } @@ -469,16 +481,21 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var, { struct intelfb_par *par = info->par; struct drm_crtc *crtc = par->crtc; - + int changed = 0; DRM_DEBUG("\n"); /* TODO add check size and pos*/ + if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset) + changed = 1; /* re-attach fb */ - if (!crtc->fb) + if (!crtc->fb) { crtc->fb = par->fb; + changed = 1; + } - drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset); + if (changed) + drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset); info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; -- cgit v1.2.3 From 9f19e79f955281b9de393219e4ad9835ffe29c49 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 17:09:51 +1100 Subject: drm: we already worked out the pitch. multiplying by 4 is just madness.. --- linux-core/intel_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 931bc1b6..52ff3a67 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -589,7 +589,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) fb->bits_per_pixel = 32; fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); fb->depth = 24; - ret = drm_buffer_object_create(dev, fb->pitch * fb->height * 4, + ret = drm_buffer_object_create(dev, fb->pitch * fb->height, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | -- cgit v1.2.3