1.6.16.4117/4.05.00.03
authorImagination Technologies/TI <imgtec>
Mon, 11 Feb 2013 00:38:15 +0000 (02:38 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Mon, 11 Feb 2013 00:38:15 +0000 (02:38 +0200)
29 files changed:
services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c
services4/3rdparty/dc_ti81xx_linux/omaplfb_displayclass.c
services4/3rdparty/dc_ti81xx_linux/omaplfb_linux.c
services4/3rdparty/linux_drm/drm_agpsupport.c
services4/3rdparty/linux_drm/drm_bufs.c
services4/3rdparty/linux_drm/drm_crtc.c
services4/3rdparty/linux_drm/drm_crtc_helper.c
services4/3rdparty/linux_drm/drm_debugfs.c
services4/3rdparty/linux_drm/drm_drv.c
services4/3rdparty/linux_drm/drm_edid.c
services4/3rdparty/linux_drm/drm_fb_helper.c
services4/3rdparty/linux_drm/drm_fops.c
services4/3rdparty/linux_drm/drm_gem.c
services4/3rdparty/linux_drm/drm_hashtab.c
services4/3rdparty/linux_drm/drm_info.c
services4/3rdparty/linux_drm/drm_ioc32.c
services4/3rdparty/linux_drm/drm_ioctl.c
services4/3rdparty/linux_drm/drm_irq.c
services4/3rdparty/linux_drm/drm_mm.c
services4/3rdparty/linux_drm/drm_modes.c
services4/3rdparty/linux_drm/drm_pci.c
services4/3rdparty/linux_drm/drm_platform.c
services4/3rdparty/linux_drm/drm_scatter.c
services4/3rdparty/linux_drm/drm_sman.c
services4/3rdparty/linux_drm/drm_stub.c
services4/3rdparty/linux_drm/drm_sysfs.c
services4/3rdparty/linux_drm/drm_vm.c
services4/srvkm/devices/sgx/sgxinit.c
services4/srvkm/env/linux/osfunc.c

index 8aac78a..248e964 100644 (file)
  *
  ******************************************************************************/
 
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
 #ifndef AUTOCONF_INCLUDED
 #include <linux/config.h>
 #endif
+#endif
 
-#include <linux/version.h>
 
 #include <asm/atomic.h>
 
@@ -290,7 +293,7 @@ OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
 
        if (psDSSDrv->get_update_mode == NULL)
        {
-               DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't get update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+//             DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't get update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
                return OMAPLFB_UPDATE_MODE_AUTO;
 //             return OMAPLFB_UPDATE_MODE_UNDEFINED;
        }
@@ -718,13 +721,13 @@ int PVR_DRM_MAKENAME(omaplfb, _Ioctl)(struct drm_device unref__ *dev, void *arg,
                        }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
-        console_lock();
+                       console_lock();
 #else
                        acquire_console_sem();
 #endif
                        ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
-        console_unlock();
+                       console_unlock();
 #else
                        release_console_sem();
 #endif
index b5ba0d1..b1bb8df 100644 (file)
@@ -828,7 +828,11 @@ static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
        unsigned long ulLCM;
        unsigned uiFBDevID = psDevInfo->uiFBDevID;
 
-       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_lock();
+#else
+        acquire_console_sem();
+#endif
 
        psLINFBInfo = registered_fb[uiFBDevID];
        if (psLINFBInfo == NULL)
@@ -970,8 +974,11 @@ static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
 ErrorModPut:
        module_put(psLINFBOwner);
 ErrorRelSem:
-       release_console_sem();
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_unlock();
+#else
+        release_console_sem();
+#endif
        return eError;
 }
 
@@ -980,7 +987,11 @@ static void OMAPLFBDeInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
        struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
        struct module *psLINFBOwner;
 
-       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_lock();
+#else
+        acquire_console_sem();
+#endif
 
        psLINFBOwner = psLINFBInfo->fbops->owner;
 
@@ -990,8 +1001,11 @@ static void OMAPLFBDeInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
        }
 
        module_put(psLINFBOwner);
-
-       release_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_unlock();
+#else
+        release_console_sem();
+#endif
 }
 
 static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
index 619624c..74134c6 100644 (file)
  *
  ******************************************************************************/
 
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
 #ifndef AUTOCONF_INCLUDED
 #include <linux/config.h>
 #endif
+#endif
 
-#include <linux/version.h>
 
 #include <asm/atomic.h>
 
@@ -241,7 +244,11 @@ void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
        int res;
        unsigned long ulYResVirtual;
 
-       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_lock();
+#else
+        acquire_console_sem();
+#endif
 
        sFBVar = psDevInfo->psLINFBInfo->var;
 
@@ -273,8 +280,11 @@ void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
                        printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
                }
        }
-
-       release_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_unlock();
+#else
+        release_console_sem();
+#endif
 }
 
 OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
@@ -489,9 +499,17 @@ OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
 {
        int res;
 #ifdef FBDEV_PRESENT
-       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_lock();
+#else
+        acquire_console_sem();
+#endif
        res = fb_blank(psDevInfo->psLINFBInfo, 0);
-       release_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_unlock();
+#else
+        release_console_sem();
+#endif 
        if (res != 0 && res != -EINVAL)
        {
                printk(KERN_WARNING DRIVER_PREFIX
@@ -507,9 +525,17 @@ OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
 
 static void OMAPLFBBlankDisplay(OMAPLFB_DEVINFO *psDevInfo)
 {
-       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_lock();
+#else
+        acquire_console_sem();
+#endif
        fb_blank(psDevInfo->psLINFBInfo, 1);
-       release_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+        console_unlock();
+#else
+        release_console_sem();
+#endif
 }
 
 static void OMAPLFBEarlySuspendHandler(struct early_suspend *h)
@@ -739,11 +765,17 @@ int PVR_DRM_MAKENAME(omaplfb, _Ioctl)(struct drm_device unref__ *dev, void *arg,
                        {
                                flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
                        }
-
-                       acquire_console_sem();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+                       console_lock();
+#else
+                       acquire_console_sem();
+#endif
                        ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
-                       release_console_sem();
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+                       console_unlock();
+#else
+                       release_console_sem();
+#endif
                        OMAPLFBCreateSwapChainUnLock(psDevInfo);
 
                        break;
index 0cb2ba5..252fdb9 100644 (file)
@@ -466,4 +466,10 @@ drm_agp_bind_pages(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_agp_bind_pages);
 
+void drm_agp_chipset_flush(struct drm_device *dev)
+{
+       agp_flush_chipset(dev->agp->bridge);
+}
+EXPORT_SYMBOL(drm_agp_chipset_flush);
+
 #endif /* __OS_HAS_AGP */
index 61e1ef9..3e257a5 100644 (file)
@@ -46,11 +46,10 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
        list_for_each_entry(entry, &dev->maplist, head) {
                /*
                 * Because the kernel-userspace ABI is fixed at a 32-bit offset
-                * while PCI resources may live above that, we only compare the
-                * lower 32 bits of the map offset for maps of type
-                * _DRM_FRAMEBUFFER or _DRM_REGISTERS.
-                * It is assumed that if a driver have more than one resource
-                * of each type, the lower 32 bits are different.
+                * while PCI resources may live above that, we ignore the map
+                * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
+                * It is assumed that each driver will have only one resource of
+                * each type.
                 */
                if (!entry->map ||
                    map->type != entry->map->type ||
@@ -60,12 +59,9 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
                case _DRM_SHM:
                        if (map->flags != _DRM_CONTAINS_LOCK)
                                break;
-                       return entry;
                case _DRM_REGISTERS:
                case _DRM_FRAME_BUFFER:
-                       if ((entry->map->offset & 0xffffffff) ==
-                           (map->offset & 0xffffffff))
-                               return entry;
+                       return entry;
                default: /* Make gcc happy */
                        ;
                }
@@ -186,6 +182,9 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
                        kfree(map);
                        return -EINVAL;
                }
+#endif
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
 #endif
                /* Some drivers preinitialize some maps, without the X Server
                 * needing to be aware of it.  Therefore, we just return success
index fe738f0..2baa670 100644 (file)
@@ -499,7 +499,6 @@ void drm_connector_cleanup(struct drm_connector *connector)
        mutex_lock(&dev->mode_config.mutex);
        drm_mode_object_put(dev, &connector->base);
        list_del(&connector->head);
-       dev->mode_config.num_connector--;
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
@@ -530,7 +529,6 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
        mutex_lock(&dev->mode_config.mutex);
        drm_mode_object_put(dev, &encoder->base);
        list_del(&encoder->head);
-       dev->mode_config.num_encoder--;
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
@@ -888,6 +886,9 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
        total_objects += dev->mode_config.num_connector;
        total_objects += dev->mode_config.num_encoder;
 
+       if (total_objects == 0)
+               return -EINVAL;
+
        group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
        if (!group->id_list)
                return -ENOMEM;
@@ -1072,9 +1073,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        uint32_t __user *encoder_id;
        struct drm_mode_group *mode_group;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
 
        /*
@@ -1112,7 +1110,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        if (card_res->count_fbs >= fb_count) {
                copied = 0;
                fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
-               list_for_each_entry(fb, &file_priv->fbs, filp_head) {
+               list_for_each_entry(fb, &file_priv->fbs, head) {
                        if (put_user(fb->base.id, fb_id + copied)) {
                                ret = -EFAULT;
                                goto out;
@@ -1246,9 +1244,6 @@ int drm_mode_getcrtc(struct drm_device *dev,
        struct drm_mode_object *obj;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
 
        obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
@@ -1317,9 +1312,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        uint64_t __user *prop_values;
        uint32_t __user *encoder_ptr;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
@@ -1439,9 +1431,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
        struct drm_encoder *encoder;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, enc_resp->encoder_id,
                                   DRM_MODE_OBJECT_ENCODER);
@@ -1497,9 +1486,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        int ret = 0;
        int i;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, crtc_req->crtc_id,
                                   DRM_MODE_OBJECT_CRTC);
@@ -1617,9 +1603,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
        struct drm_crtc *crtc;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        if (!req->flags) {
                DRM_ERROR("no operation set\n");
                return -EINVAL;
@@ -1684,9 +1667,6 @@ int drm_mode_addfb(struct drm_device *dev,
        struct drm_framebuffer *fb;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        if ((config->min_width > r->width) || (r->width > config->max_width)) {
                DRM_ERROR("mode new framebuffer width not within limits\n");
                return -EINVAL;
@@ -1698,7 +1678,7 @@ int drm_mode_addfb(struct drm_device *dev,
 
        mutex_lock(&dev->mode_config.mutex);
 
-       /* TODO check buffer is sufficiently large */
+       /* TODO check buffer is sufficently large */
        /* TODO setup destructor callback */
 
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
@@ -1744,12 +1724,9 @@ int drm_mode_rmfb(struct drm_device *dev,
        int ret = 0;
        int found = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
-       /* TODO check that we really get a framebuffer back. */
+       /* TODO check that we realy get a framebuffer back. */
        if (!obj) {
                DRM_ERROR("mode invalid framebuffer id\n");
                ret = -EINVAL;
@@ -1803,9 +1780,6 @@ int drm_mode_getfb(struct drm_device *dev,
        struct drm_framebuffer *fb;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
@@ -1839,9 +1813,6 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        int num_clips;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
@@ -2025,9 +1996,6 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
        struct drm_mode_modeinfo *umode = &mode_cmd->mode;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
 
        obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2074,9 +2042,6 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev,
        struct drm_mode_modeinfo *umode = &mode_cmd->mode;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
 
        obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2246,9 +2211,6 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
        uint64_t __user *values_ptr;
        uint32_t __user *blob_length_ptr;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
        if (!obj) {
@@ -2371,9 +2333,6 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
        int ret = 0;
        void *blob_ptr;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
        if (!obj) {
@@ -2434,9 +2393,6 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
        int ret = -EINVAL;
        int i;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
 
        obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2553,9 +2509,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
        int size;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
@@ -2607,9 +2560,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
        int size;
        int ret = 0;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
@@ -2724,56 +2674,3 @@ out:
        mutex_unlock(&dev->mode_config.mutex);
        return ret;
 }
-
-void drm_mode_config_reset(struct drm_device *dev)
-{
-       struct drm_crtc *crtc;
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               if (crtc->funcs->reset)
-                       crtc->funcs->reset(crtc);
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               if (encoder->funcs->reset)
-                       encoder->funcs->reset(encoder);
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               if (connector->funcs->reset)
-                       connector->funcs->reset(connector);
-}
-EXPORT_SYMBOL(drm_mode_config_reset);
-
-int drm_mode_create_dumb_ioctl(struct drm_device *dev,
-                              void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_create_dumb *args = data;
-
-       if (!dev->driver->dumb_create)
-               return -ENOSYS;
-       return dev->driver->dumb_create(file_priv, dev, args);
-}
-
-int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
-                            void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_map_dumb *args = data;
-
-       /* call driver ioctl to get mmap offset */
-       if (!dev->driver->dumb_map_offset)
-               return -ENOSYS;
-
-       return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
-}
-
-int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
-                               void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_destroy_dumb *args = data;
-
-       if (!dev->driver->dumb_destroy)
-               return -ENOSYS;
-
-       return dev->driver->dumb_destroy(file_priv, dev, args->handle);
-}
index f88a9b2..2d4e17a 100644 (file)
@@ -336,20 +336,20 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
                              struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
+       struct drm_display_mode *adjusted_mode, saved_mode;
        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
        struct drm_encoder_helper_funcs *encoder_funcs;
        int saved_x, saved_y;
        struct drm_encoder *encoder;
        bool ret = true;
 
+       adjusted_mode = drm_mode_duplicate(dev, mode);
+
        crtc->enabled = drm_helper_crtc_in_use(crtc);
+
        if (!crtc->enabled)
                return true;
 
-       adjusted_mode = drm_mode_duplicate(dev, mode);
-
-       saved_hwmode = crtc->hwmode;
        saved_mode = crtc->mode;
        saved_x = crtc->x;
        saved_y = crtc->y;
@@ -427,20 +427,11 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 
        }
 
-       /* Store real post-adjustment hardware mode. */
-       crtc->hwmode = *adjusted_mode;
-
-       /* Calculate and store various constants which
-        * are later needed by vblank and swap-completion
-        * timestamping. They are derived from true hwmode.
-        */
-       drm_calc_timestamping_constants(crtc);
-
+       /* XXX free adjustedmode */
+       drm_mode_destroy(dev, adjusted_mode);
        /* FIXME: add subpixel order */
 done:
-       drm_mode_destroy(dev, adjusted_mode);
        if (!ret) {
-               crtc->hwmode = saved_hwmode;
                crtc->mode = saved_mode;
                crtc->x = saved_x;
                crtc->y = saved_y;
@@ -495,17 +486,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 
        crtc_funcs = set->crtc->helper_private;
 
-       if (!set->mode)
-               set->fb = NULL;
-
        if (set->fb) {
                DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
                                set->crtc->base.id, set->fb->base.id,
                                (int)set->num_connectors, set->x, set->y);
        } else {
-               DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-               set->mode = NULL;
-               set->num_connectors = 0;
+               DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
+                               set->crtc->base.id, (int)set->num_connectors,
+                               set->x, set->y);
        }
 
        dev = set->crtc->dev;
@@ -560,11 +548,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        mode_changed = true;
                } else if (set->fb == NULL) {
                        mode_changed = true;
-               } else if (set->fb->depth != set->crtc->fb->depth) {
-                       mode_changed = true;
-               } else if (set->fb->bits_per_pixel !=
-                          set->crtc->fb->bits_per_pixel) {
-                       mode_changed = true;
                } else
                        fb_changed = true;
        }
@@ -655,8 +638,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                mode_changed = true;
 
        if (mode_changed) {
-               set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
-               if (set->crtc->enabled) {
+               set->crtc->enabled = (set->mode != NULL);
+               if (set->mode != NULL) {
                        DRM_DEBUG_KMS("attempting to set mode from"
                                        " userspace\n");
                        drm_mode_debug_printmodeline(set->mode);
@@ -667,16 +650,9 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                                                      old_fb)) {
                                DRM_ERROR("failed to set mode on [CRTC:%d]\n",
                                          set->crtc->base.id);
-                               set->crtc->fb = old_fb;
                                ret = -EINVAL;
                                goto fail;
                        }
-                       DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
-                       for (i = 0; i < set->num_connectors; i++) {
-                               DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
-                                             drm_get_connector_name(set->connectors[i]));
-                               set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
-                       }
                }
                drm_helper_disable_unused_functions(dev);
        } else if (fb_changed) {
@@ -688,10 +664,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        set->crtc->fb = set->fb;
                ret = crtc_funcs->mode_set_base(set->crtc,
                                                set->x, set->y, old_fb);
-               if (ret != 0) {
-                       set->crtc->fb = old_fb;
+               if (ret != 0)
                        goto fail;
-               }
+       }
+       DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+       for (i = 0; i < set->num_connectors; i++) {
+               DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+                             drm_get_connector_name(set->connectors[i]));
+               set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
        }
 
        kfree(save_connectors);
index 9d2668a..9d8c892 100644 (file)
@@ -90,6 +90,7 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
        struct drm_device *dev = minor->dev;
        struct dentry *ent;
        struct drm_info_node *tmp;
+       char name[64];
        int i, ret;
 
        for (i = 0; i < count; i++) {
@@ -107,9 +108,6 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
                                          root, tmp, &drm_debugfs_fops);
                if (!ent) {
-                       char name[64];
-                       strncpy(name, root->d_name.name,
-                                               min(root->d_name.len, 64U));
                        DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
                                  name, files[i].name);
                        kfree(tmp);
index 93a112d..271835a 100644 (file)
@@ -67,7 +67,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
 
        DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -151,10 +150,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
@@ -238,6 +234,49 @@ int drm_lastclose(struct drm_device * dev)
        return 0;
 }
 
+/**
+ * Module initialization. Called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported).
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Initializes an array of drm_device structures, and attempts to
+ * initialize all available devices, using consecutive minors, registering the
+ * stubs and initializing the device.
+ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
+ */
+int drm_init(struct drm_driver *driver)
+{
+       DRM_DEBUG("\n");
+       INIT_LIST_HEAD(&driver->device_list);
+
+       if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
+               return drm_platform_init(driver);
+       else
+               return drm_pci_init(driver);
+}
+
+EXPORT_SYMBOL(drm_init);
+
+void drm_exit(struct drm_driver *driver)
+{
+       struct drm_device *dev, *tmp;
+       DRM_DEBUG("\n");
+
+       if (driver->driver_features & DRIVER_MODESET) {
+               pci_unregister_driver(&driver->pci_driver);
+       } else {
+               list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+                       drm_put_dev(dev);
+       }
+
+       DRM_INFO("Module unloaded\n");
+}
+
+EXPORT_SYMBOL(drm_exit);
+
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
        .owner = THIS_MODULE,
index 7425e5c..a245d17 100644 (file)
@@ -127,23 +127,6 @@ static const u8 edid_header[] = {
        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
- /*
- * Sanity check the header of the base EDID block.  Return 8 if the header
- * is perfect, down to 0 if it's totally wrong.
- */
-int drm_edid_header_is_valid(const u8 *raw_edid)
-{
-       int i, score = 0;
-
-       for (i = 0; i < sizeof(edid_header); i++)
-               if (raw_edid[i] == edid_header[i])
-                       score++;
-
-       return score;
-}
-EXPORT_SYMBOL(drm_edid_header_is_valid);
-
-
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -156,7 +139,12 @@ drm_edid_block_valid(u8 *raw_edid)
        struct edid *edid = (struct edid *)raw_edid;
 
        if (raw_edid[0] == 0x00) {
-               int score = drm_edid_header_is_valid(raw_edid);
+               int score = 0;
+
+               for (i = 0; i < sizeof(edid_header); i++)
+                       if (raw_edid[i] == edid_header[i])
+                               score++;
+
                if (score == 8) ;
                else if (score >= 6) {
                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
@@ -196,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)
 
 bad:
        if (raw_edid) {
-               printk(KERN_ERR "Raw EDID:\n");
-               print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
-                              raw_edid, EDID_LENGTH, false);
+               DRM_ERROR("Raw EDID:\n");
+               print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
+               printk("\n");
        }
        return 0;
 }
@@ -242,43 +230,24 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
                      int block, int len)
 {
        unsigned char start = block * EDID_LENGTH;
-       int ret, retries = 5;
-
-       /* The core i2c driver will automatically retry the transfer if the
-        * adapter reports EAGAIN. However, we find that bit-banging transfers
-        * are susceptible to errors under a heavily loaded machine and
-        * generate spurious NAKs and timeouts. Retrying the transfer
-        * of the individual block a few times seems to overcome this.
-        */
-       do {
-               struct i2c_msg msgs[] = {
-                       {
-                               .addr   = DDC_ADDR,
-                               .flags  = 0,
-                               .len    = 1,
-                               .buf    = &start,
-                       }, {
-                               .addr   = DDC_ADDR,
-                               .flags  = I2C_M_RD,
-                               .len    = len,
-                               .buf    = buf,
-                       }
-               };
-               ret = i2c_transfer(adapter, msgs, 2);
-       } while (ret != 2 && --retries);
-
-       return ret == 2 ? 0 : -1;
-}
+       struct i2c_msg msgs[] = {
+               {
+                       .addr   = DDC_ADDR,
+                       .flags  = 0,
+                       .len    = 1,
+                       .buf    = &start,
+               }, {
+                       .addr   = DDC_ADDR,
+                       .flags  = I2C_M_RD,
+                       .len    = len,
+                       .buf    = buf,
+               }
+       };
 
-static bool drm_edid_is_zero(u8 *in_edid, int length)
-{
-       int i;
-       u32 *raw_edid = (u32 *)in_edid;
+       if (i2c_transfer(adapter, msgs, 2) == 2)
+               return 0;
 
-       for (i = 0; i < length / 4; i++)
-               if (*(raw_edid + i) != 0)
-                       return false;
-       return true;
+       return -1;
 }
 
 static u8 *
@@ -296,10 +265,6 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
                        goto out;
                if (drm_edid_block_valid(block))
                        break;
-               if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
-                       connector->null_edid_counter++;
-                       goto carp;
-               }
        }
        if (i == 4)
                goto carp;
@@ -484,11 +449,12 @@ static void edid_fixup_preferred(struct drm_connector *connector,
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
                                           int hsize, int vsize, int fresh)
 {
-       struct drm_display_mode *mode = NULL;
        int i;
+       struct drm_display_mode *ptr, *mode;
 
+       mode = NULL;
        for (i = 0; i < drm_num_dmt_modes; i++) {
-               const struct drm_display_mode *ptr = &drm_dmt_modes[i];
+               ptr = &drm_dmt_modes[i];
                if (hsize == ptr->hdisplay &&
                        vsize == ptr->vdisplay &&
                        fresh == drm_mode_vrefresh(ptr)) {
@@ -919,7 +885,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 }
 
 static bool
-mode_is_rb(const struct drm_display_mode *mode)
+mode_is_rb(struct drm_display_mode *mode)
 {
        return (mode->htotal - mode->hdisplay == 160) &&
               (mode->hsync_end - mode->hdisplay == 80) &&
@@ -928,8 +894,7 @@ mode_is_rb(const struct drm_display_mode *mode)
 }
 
 static bool
-mode_in_hsync_range(const struct drm_display_mode *mode,
-                   struct edid *edid, u8 *t)
+mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
 {
        int hsync, hmin, hmax;
 
@@ -945,8 +910,7 @@ mode_in_hsync_range(const struct drm_display_mode *mode,
 }
 
 static bool
-mode_in_vsync_range(const struct drm_display_mode *mode,
-                   struct edid *edid, u8 *t)
+mode_in_vsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
 {
        int vsync, vmin, vmax;
 
@@ -977,7 +941,7 @@ range_pixel_clock(struct edid *edid, u8 *t)
 }
 
 static bool
-mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
+mode_in_range(struct drm_display_mode *mode, struct edid *edid,
              struct detailed_timing *timing)
 {
        u32 max_clock;
@@ -1324,7 +1288,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
 /**
  * Search EDID for CEA extension block.
  */
-u8 *drm_find_cea_extension(struct edid *edid)
+static u8 *drm_find_cea_extension(struct edid *edid)
 {
        u8 *edid_ext = NULL;
        int i;
@@ -1345,7 +1309,6 @@ u8 *drm_find_cea_extension(struct edid *edid)
 
        return edid_ext;
 }
-EXPORT_SYMBOL(drm_find_cea_extension);
 
 /**
  * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
@@ -1439,73 +1402,6 @@ end:
 }
 EXPORT_SYMBOL(drm_detect_monitor_audio);
 
-/**
- * drm_add_display_info - pull display info out if present
- * @edid: EDID data
- * @info: display info (attached to connector)
- *
- * Grab any available display info and stuff it into the drm_display_info
- * structure that's part of the connector.  Useful for tracking bpp and
- * color spaces.
- */
-static void drm_add_display_info(struct edid *edid,
-                                struct drm_display_info *info)
-{
-       u8 *edid_ext;
-
-       info->width_mm = edid->width_cm * 10;
-       info->height_mm = edid->height_cm * 10;
-
-       /* driver figures it out in this case */
-       info->bpc = 0;
-       info->color_formats = 0;
-
-       /* Only defined for 1.4 with digital displays */
-       if (edid->revision < 4)
-               return;
-
-       if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
-               return;
-
-       switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
-       case DRM_EDID_DIGITAL_DEPTH_6:
-               info->bpc = 6;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_8:
-               info->bpc = 8;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_10:
-               info->bpc = 10;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_12:
-               info->bpc = 12;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_14:
-               info->bpc = 14;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_16:
-               info->bpc = 16;
-               break;
-       case DRM_EDID_DIGITAL_DEPTH_UNDEF:
-       default:
-               info->bpc = 0;
-               break;
-       }
-
-       info->color_formats = DRM_COLOR_FORMAT_RGB444;
-       if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444)
-               info->color_formats = DRM_COLOR_FORMAT_YCRCB444;
-       if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422)
-               info->color_formats = DRM_COLOR_FORMAT_YCRCB422;
-
-       /* Get data from CEA blocks if present */
-       edid_ext = drm_find_cea_extension(edid);
-       if (!edid_ext)
-               return;
-
-       info->cea_rev = edid_ext[1];
-}
-
 /**
  * drm_add_edid_modes - add modes from EDID data, if available
  * @connector: connector we're probing
@@ -1554,7 +1450,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
        if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
                edid_fixup_preferred(connector, quirks);
 
-       drm_add_display_info(edid, &connector->display_info);
+       connector->display_info.width_mm = edid->width_cm * 10;
+       connector->display_info.height_mm = edid->height_cm * 10;
 
        return num_modes;
 }
@@ -1575,7 +1472,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
                        int hdisplay, int vdisplay)
 {
        int i, count, num_modes = 0;
-       struct drm_display_mode *mode;
+       struct drm_display_mode *mode, *ptr;
        struct drm_device *dev = connector->dev;
 
        count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
@@ -1585,7 +1482,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
                vdisplay = 0;
 
        for (i = 0; i < count; i++) {
-               const struct drm_display_mode *ptr = &drm_dmt_modes[i];
+               ptr = &drm_dmt_modes[i];
                if (hdisplay && vdisplay) {
                        /*
                         * Only when two are valid, they will be used to check
index f7c6854..d2849e4 100644 (file)
@@ -70,50 +70,174 @@ fail:
 }
 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
 
+/**
+ * drm_fb_helper_connector_parse_command_line - parse command line for connector
+ * @connector - connector to parse line for
+ * @mode_option - per connector mode option
+ *
+ * This parses the connector specific then generic command lines for
+ * modes and options to configure the connector.
+ *
+ * This uses the same parameters as the fb modedb.c, except for extra
+ *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
+ *
+ * enable/enable Digital/disable bit at the end
+ */
+static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn,
+                                                      const char *mode_option)
+{
+       const char *name;
+       unsigned int namelen;
+       int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+       unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
+       int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+       int i;
+       enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
+       struct drm_fb_helper_cmdline_mode *cmdline_mode;
+       struct drm_connector *connector;
+
+       if (!fb_helper_conn)
+               return false;
+       connector = fb_helper_conn->connector;
+
+       cmdline_mode = &fb_helper_conn->cmdline_mode;
+       if (!mode_option)
+               mode_option = fb_mode_option;
+
+       if (!mode_option) {
+               cmdline_mode->specified = false;
+               return false;
+       }
+
+       name = mode_option;
+       namelen = strlen(name);
+       for (i = namelen-1; i >= 0; i--) {
+               switch (name[i]) {
+               case '@':
+                       namelen = i;
+                       if (!refresh_specified && !bpp_specified &&
+                           !yres_specified) {
+                               refresh = simple_strtol(&name[i+1], NULL, 10);
+                               refresh_specified = 1;
+                               if (cvt || rb)
+                                       cvt = 0;
+                       } else
+                               goto done;
+                       break;
+               case '-':
+                       namelen = i;
+                       if (!bpp_specified && !yres_specified) {
+                               bpp = simple_strtol(&name[i+1], NULL, 10);
+                               bpp_specified = 1;
+                               if (cvt || rb)
+                                       cvt = 0;
+                       } else
+                               goto done;
+                       break;
+               case 'x':
+                       if (!yres_specified) {
+                               yres = simple_strtol(&name[i+1], NULL, 10);
+                               yres_specified = 1;
+                       } else
+                               goto done;
+               case '0' ... '9':
+                       break;
+               case 'M':
+                       if (!yres_specified)
+                               cvt = 1;
+                       break;
+               case 'R':
+                       if (cvt)
+                               rb = 1;
+                       break;
+               case 'm':
+                       if (!cvt)
+                               margins = 1;
+                       break;
+               case 'i':
+                       if (!cvt)
+                               interlace = 1;
+                       break;
+               case 'e':
+                       force = DRM_FORCE_ON;
+                       break;
+               case 'D':
+                       if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
+                           (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
+                               force = DRM_FORCE_ON;
+                       else
+                               force = DRM_FORCE_ON_DIGITAL;
+                       break;
+               case 'd':
+                       force = DRM_FORCE_OFF;
+                       break;
+               default:
+                       goto done;
+               }
+       }
+       if (i < 0 && yres_specified) {
+               xres = simple_strtol(name, NULL, 10);
+               res_specified = 1;
+       }
+done:
+
+       DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
+               drm_get_connector_name(connector), xres, yres,
+               (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
+               "", (margins) ? " with margins" : "", (interlace) ?
+               " interlaced" : "");
+
+       if (force) {
+               const char *s;
+               switch (force) {
+               case DRM_FORCE_OFF: s = "OFF"; break;
+               case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
+               default:
+               case DRM_FORCE_ON: s = "ON"; break;
+               }
+
+               DRM_INFO("forcing %s connector %s\n",
+                        drm_get_connector_name(connector), s);
+               connector->force = force;
+       }
+
+       if (res_specified) {
+               cmdline_mode->specified = true;
+               cmdline_mode->xres = xres;
+               cmdline_mode->yres = yres;
+       }
+
+       if (refresh_specified) {
+               cmdline_mode->refresh_specified = true;
+               cmdline_mode->refresh = refresh;
+       }
+
+       if (bpp_specified) {
+               cmdline_mode->bpp_specified = true;
+               cmdline_mode->bpp = bpp;
+       }
+       cmdline_mode->rb = rb ? true : false;
+       cmdline_mode->cvt = cvt  ? true : false;
+       cmdline_mode->interlace = interlace ? true : false;
+
+       return true;
+}
+
 static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
 {
        struct drm_fb_helper_connector *fb_helper_conn;
        int i;
 
        for (i = 0; i < fb_helper->connector_count; i++) {
-               struct drm_cmdline_mode *mode;
-               struct drm_connector *connector;
                char *option = NULL;
 
                fb_helper_conn = fb_helper->connector_info[i];
-               connector = fb_helper_conn->connector;
-               mode = &fb_helper_conn->cmdline_mode;
 
                /* do something on return - turn off connector maybe */
-               if (fb_get_options(drm_get_connector_name(connector), &option))
+               if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option))
                        continue;
 
-               if (drm_mode_parse_command_line_for_connector(option,
-                                                             connector,
-                                                             mode)) {
-                       if (mode->force) {
-                               const char *s;
-                               switch (mode->force) {
-                               case DRM_FORCE_OFF: s = "OFF"; break;
-                               case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
-                               default:
-                               case DRM_FORCE_ON: s = "ON"; break;
-                               }
-
-                               DRM_INFO("forcing %s connector %s\n",
-                                        drm_get_connector_name(connector), s);
-                               connector->force = mode->force;
-                       }
-
-                       DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
-                                     drm_get_connector_name(connector),
-                                     mode->xres, mode->yres,
-                                     mode->refresh_specified ? mode->refresh : 60,
-                                     mode->rb ? " reduced blanking" : "",
-                                     mode->margins ? " with margins" : "",
-                                     mode->interlace ?  " interlaced" : "");
-               }
-
+               drm_fb_helper_connector_parse_command_line(fb_helper_conn, option);
        }
        return 0;
 }
@@ -218,22 +342,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
-bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
-{
-       bool error = false;
-       int i, ret;
-       for (i = 0; i < fb_helper->crtc_count; i++) {
-               struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
-               ret = drm_crtc_helper_set_config(mode_set);
-               if (ret)
-                       error = true;
-       }
-       return error;
-}
-EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
-
 bool drm_fb_helper_force_kernel_mode(void)
 {
+       int i = 0;
        bool ret, error = false;
        struct drm_fb_helper *helper;
 
@@ -241,12 +352,12 @@ bool drm_fb_helper_force_kernel_mode(void)
                return false;
 
        list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-               if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
-                       continue;
-
-               ret = drm_fb_helper_restore_fbdev_mode(helper);
-               if (ret)
-                       error = true;
+               for (i = 0; i < helper->crtc_count; i++) {
+                       struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
+                       ret = drm_crtc_helper_set_config(mode_set);
+                       if (ret)
+                               error = true;
+               }
        }
        return error;
 }
@@ -256,6 +367,7 @@ int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
 {
        printk(KERN_ERR "panic occurred, switching back to text console\n");
        return drm_fb_helper_force_kernel_mode();
+       return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_panic);
 
@@ -515,11 +627,6 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
                value = (red << info->var.red.offset) |
                        (green << info->var.green.offset) |
                        (blue << info->var.blue.offset);
-               if (info->var.transp.length > 0) {
-                       u32 mask = (1 << info->var.transp.length) - 1;
-                       mask <<= info->var.transp.offset;
-                       value |= mask;
-               }
                palette[regno] = value;
                return 0;
        }
@@ -565,7 +672,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
        struct drm_crtc_helper_funcs *crtc_funcs;
        u16 *red, *green, *blue, *transp;
        struct drm_crtc *crtc;
-       int i, j, rc = 0;
+       int i, rc = 0;
        int start;
 
        for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -578,7 +685,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
                transp = cmap->transp;
                start = cmap->start;
 
-               for (j = 0; j < cmap->len; j++) {
+               for (i = 0; i < cmap->len; i++) {
                        u16 hred, hgreen, hblue, htransp = 0xffff;
 
                        hred = *red++;
@@ -776,7 +883,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
        /* first up get a count of crtcs now in use and new min/maxes width/heights */
        for (i = 0; i < fb_helper->connector_count; i++) {
                struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
-               struct drm_cmdline_mode *cmdline_mode;
+               struct drm_fb_helper_cmdline_mode *cmdline_mode;
 
                cmdline_mode = &fb_helper_conn->cmdline_mode;
 
@@ -878,8 +985,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
                FB_VISUAL_TRUECOLOR;
-       info->fix.mmio_start = 0;
-       info->fix.mmio_len = 0;
        info->fix.type_aux = 0;
        info->fix.xpanstep = 1; /* doing it in hw */
        info->fix.ypanstep = 1; /* doing it in hw */
@@ -900,7 +1005,6 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
        info->var.xres_virtual = fb->width;
        info->var.yres_virtual = fb->height;
        info->var.bits_per_pixel = fb->bits_per_pixel;
-       info->var.accel_flags = FB_ACCELF_TEXT;
        info->var.xoffset = 0;
        info->var.yoffset = 0;
        info->var.activate = FB_ACTIVATE_NOW;
@@ -998,7 +1102,7 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_conn
 
 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 {
-       struct drm_cmdline_mode *cmdline_mode;
+       struct drm_fb_helper_cmdline_mode *cmdline_mode;
        cmdline_mode = &fb_connector->cmdline_mode;
        return cmdline_mode->specified;
 }
@@ -1006,7 +1110,7 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
                                                      int width, int height)
 {
-       struct drm_cmdline_mode *cmdline_mode;
+       struct drm_fb_helper_cmdline_mode *cmdline_mode;
        struct drm_display_mode *mode = NULL;
 
        cmdline_mode = &fb_helper_conn->cmdline_mode;
@@ -1038,8 +1142,19 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
        }
 
 create_mode:
-       mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
-                                                cmdline_mode);
+       if (cmdline_mode->cvt)
+               mode = drm_cvt_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->rb, cmdline_mode->interlace,
+                                   cmdline_mode->margins);
+       else
+               mode = drm_gtf_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->interlace,
+                                   cmdline_mode->margins);
+       drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
        list_add(&mode->head, &fb_helper_conn->connector->modes);
        return mode;
 }
@@ -1380,33 +1495,17 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 }
 EXPORT_SYMBOL(drm_fb_helper_initial_config);
 
-/**
- * drm_fb_helper_hotplug_event - respond to a hotplug notification by
- *                               probing all the outputs attached to the fb.
- * @fb_helper: the drm_fb_helper
- *
- * LOCKING:
- * Called at runtime, must take mode config lock.
- *
- * Scan the connectors attached to the fb_helper and try to put together a
- * setup after *notification of a change in output configuration.
- *
- * RETURNS:
- * 0 on success and a non-zero error code otherwise.
- */
-int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
+bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
-       struct drm_device *dev = fb_helper->dev;
        int count = 0;
        u32 max_width, max_height, bpp_sel;
        bool bound = false, crtcs_bound = false;
        struct drm_crtc *crtc;
 
        if (!fb_helper->fb)
-               return 0;
+               return false;
 
-       mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+       list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
                if (crtc->fb)
                        crtcs_bound = true;
                if (crtc->fb == fb_helper->fb)
@@ -1415,8 +1514,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
        if (!bound && crtcs_bound) {
                fb_helper->delayed_hotplug = true;
-               mutex_unlock(&dev->mode_config.mutex);
-               return 0;
+               return false;
        }
        DRM_DEBUG_KMS("\n");
 
@@ -1427,30 +1525,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
        count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
                                                    max_height);
        drm_setup_crtcs(fb_helper);
-       mutex_unlock(&dev->mode_config.mutex);
 
        return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
 }
 EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
 
-/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
- * but the module doesn't depend on any fb console symbols.  At least
- * attempt to load fbcon to avoid leaving the system without a usable console.
- */
-#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
-static int __init drm_fb_helper_modinit(void)
-{
-       const char *name = "fbcon";
-       struct module *fbcon;
-
-       mutex_lock(&module_mutex);
-       fbcon = find_module(name);
-       mutex_unlock(&module_mutex);
-
-       if (!fbcon)
-               request_module_nowait(name);
-       return 0;
-}
-
-module_init(drm_fb_helper_modinit);
-#endif
index 2ec7d48..a39794b 100644 (file)
@@ -236,8 +236,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
                return -EBUSY;  /* No exclusive opens */
        if (!drm_cpu_valid())
                return -EINVAL;
-       if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
-               return -EINVAL;
 
        DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
 
index 186d62e..ea1c4b0 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
-#include <linux/shmem_fs.h>
 #include "drmP.h"
 
 /** @file drm_gem.c
@@ -102,7 +101,7 @@ drm_gem_init(struct drm_device *dev)
 
        dev->mm_private = mm;
 
-       if (drm_ht_create(&mm->offset_hash, 12)) {
+       if (drm_ht_create(&mm->offset_hash, 19)) {
                kfree(mm);
                return -ENOMEM;
        }
@@ -129,7 +128,7 @@ drm_gem_destroy(struct drm_device *dev)
 }
 
 /**
- * Initialize an already allocated GEM object of the specified size with
+ * Initialize an already allocate GEM object of the specified size with
  * shmfs backing store.
  */
 int drm_gem_object_init(struct drm_device *dev,
@@ -150,27 +149,6 @@ int drm_gem_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_object_init);
 
-/**
- * Initialize an already allocated GEM object of the specified size with
- * no GEM provided backing store. Instead the caller is responsible for
- * backing the object and handling it.
- */
-int drm_gem_private_object_init(struct drm_device *dev,
-                       struct drm_gem_object *obj, size_t size)
-{
-       BUG_ON((size & (PAGE_SIZE - 1)) != 0);
-
-       obj->dev = dev;
-       obj->filp = NULL;
-
-       kref_init(&obj->refcount);
-       atomic_set(&obj->handle_count, 0);
-       obj->size = size;
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_gem_private_object_init);
-
 /**
  * Allocate a GEM object of the specified size with shmfs backing store
  */
@@ -203,7 +181,7 @@ EXPORT_SYMBOL(drm_gem_object_alloc);
 /**
  * Removes the mapping from handle to filp for this object.
  */
-int
+static int
 drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 {
        struct drm_device *dev;
@@ -232,13 +210,10 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
        idr_remove(&filp->object_idr, handle);
        spin_unlock(&filp->table_lock);
 
-       if (dev->driver->gem_close_object)
-               dev->driver->gem_close_object(obj, filp);
        drm_gem_object_handle_unreference_unlocked(obj);
 
        return 0;
 }
-EXPORT_SYMBOL(drm_gem_handle_delete);
 
 /**
  * Create a handle for this object. This adds a handle reference
@@ -250,8 +225,7 @@ drm_gem_handle_create(struct drm_file *file_priv,
                       struct drm_gem_object *obj,
                       u32 *handlep)
 {
-       struct drm_device *dev = obj->dev;
-       int ret;
+       int     ret;
 
        /*
         * Get the user-visible handle using idr.
@@ -272,15 +246,6 @@ again:
                return ret;
 
        drm_gem_object_handle_reference(obj);
-
-       if (dev->driver->gem_open_object) {
-               ret = dev->driver->gem_open_object(obj, file_priv);
-               if (ret) {
-                       drm_gem_handle_delete(file_priv, *handlep);
-                       return ret;
-               }
-       }
-
        return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
@@ -435,12 +400,7 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
 static int
 drm_gem_object_release_handle(int id, void *ptr, void *data)
 {
-       struct drm_file *file_priv = data;
        struct drm_gem_object *obj = ptr;
-       struct drm_device *dev = obj->dev;
-
-       if (dev->driver->gem_close_object)
-               dev->driver->gem_close_object(obj, file_priv);
 
        drm_gem_object_handle_unreference_unlocked(obj);
 
@@ -456,7 +416,7 @@ void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
        idr_for_each(&file_private->object_idr,
-                    &drm_gem_object_release_handle, file_private);
+                    &drm_gem_object_release_handle, NULL);
 
        idr_remove_all(&file_private->object_idr);
        idr_destroy(&file_private->object_idr);
@@ -465,8 +425,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 void
 drm_gem_object_release(struct drm_gem_object *obj)
 {
-       if (obj->filp)
-           fput(obj->filp);
+       fput(obj->filp);
 }
 EXPORT_SYMBOL(drm_gem_object_release);
 
@@ -539,12 +498,11 @@ EXPORT_SYMBOL(drm_gem_vm_open);
 void drm_gem_vm_close(struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
-       struct drm_device *dev = obj->dev;
 
-       mutex_lock(&dev->struct_mutex);
+       mutex_lock(&obj->dev->struct_mutex);
        drm_vm_close_locked(vma);
        drm_gem_object_unreference(obj);
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
index e3a7568..a93d7b4 100644 (file)
 
 int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
-       unsigned int size = 1 << order;
+       unsigned int i;
 
+       ht->size = 1 << order;
        ht->order = order;
+       ht->fill = 0;
        ht->table = NULL;
-       if (size <= PAGE_SIZE / sizeof(*ht->table))
-               ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
-       else
-               ht->table = vzalloc(size*sizeof(*ht->table));
+       ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
+       if (!ht->use_vmalloc) {
+               ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
+       }
+       if (!ht->table) {
+               ht->use_vmalloc = 1;
+               ht->table = vmalloc(ht->size*sizeof(*ht->table));
+       }
        if (!ht->table) {
                DRM_ERROR("Out of memory for hash table\n");
                return -ENOMEM;
        }
+       for (i=0; i< ht->size; ++i) {
+               INIT_HLIST_HEAD(&ht->table[i]);
+       }
        return 0;
 }
 EXPORT_SYMBOL(drm_ht_create);
@@ -171,6 +180,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
        list = drm_ht_find_key(ht, key);
        if (list) {
                hlist_del_init(list);
+               ht->fill--;
                return 0;
        }
        return -EINVAL;
@@ -179,6 +189,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
        hlist_del_init(&item->head);
+       ht->fill--;
        return 0;
 }
 EXPORT_SYMBOL(drm_ht_remove_item);
@@ -186,10 +197,10 @@ EXPORT_SYMBOL(drm_ht_remove_item);
 void drm_ht_remove(struct drm_open_hash *ht)
 {
        if (ht->table) {
-               if ((PAGE_SIZE / sizeof(*ht->table)) >> ht->order)
-                       kfree(ht->table);
-               else
+               if (ht->use_vmalloc)
                        vfree(ht->table);
+               else
+                       kfree(ht->table);
                ht->table = NULL;
        }
 }
index ab1162d..3cdbaf3 100644 (file)
@@ -47,19 +47,30 @@ int drm_name_info(struct seq_file *m, void *data)
        struct drm_minor *minor = node->minor;
        struct drm_device *dev = minor->dev;
        struct drm_master *master = minor->master;
-       const char *bus_name;
+
        if (!master)
                return 0;
 
-       bus_name = dev->driver->bus->get_name(dev);
-       if (master->unique) {
-               seq_printf(m, "%s %s %s\n",
-                          bus_name,
-                          dev_name(dev->dev), master->unique);
+       if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
+               if (master->unique) {
+                       seq_printf(m, "%s %s %s\n",
+                                       dev->driver->platform_device->name,
+                                       dev_name(dev->dev), master->unique);
+               } else {
+                       seq_printf(m, "%s\n",
+                               dev->driver->platform_device->name);
+               }
        } else {
-               seq_printf(m, "%s %s\n",
-                          bus_name, dev_name(dev->dev));
+               if (master->unique) {
+                       seq_printf(m, "%s %s %s\n",
+                               dev->driver->pci_driver.name,
+                               dev_name(dev->dev), master->unique);
+               } else {
+                       seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
+                               dev_name(dev->dev));
+               }
        }
+
        return 0;
 }
 
@@ -272,18 +283,17 @@ int drm_vma_info(struct seq_file *m, void *data)
 #endif
 
        mutex_lock(&dev->struct_mutex);
-       seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
+       seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n",
                   atomic_read(&dev->vma_count),
-                  high_memory, (void *)virt_to_phys(high_memory));
+                  high_memory, (u64)virt_to_phys(high_memory));
 
        list_for_each_entry(pt, &dev->vmalist, head) {
                vma = pt->vma;
                if (!vma)
                        continue;
                seq_printf(m,
-                          "\n%5d 0x%pK-0x%pK %c%c%c%c%c%c 0x%08lx000",
-                          pt->pid,
-                          (void *)vma->vm_start, (void *)vma->vm_end,
+                          "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
+                          pt->pid, vma->vm_start, vma->vm_end,
                           vma->vm_flags & VM_READ ? 'r' : '-',
                           vma->vm_flags & VM_WRITE ? 'w' : '-',
                           vma->vm_flags & VM_EXEC ? 'x' : '-',
index 4a058c7..d61d185 100644 (file)
@@ -28,7 +28,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ratelimit.h>
 
 #include "drmP.h"
 #include "drm_core.h"
@@ -254,10 +253,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
                return -EFAULT;
 
        m32.handle = (unsigned long)handle;
-       if (m32.handle != (unsigned long)handle)
-               printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
-                                  " %p for type %d offset %x\n",
-                                  handle, m32.type, m32.offset);
+       if (m32.handle != (unsigned long)handle && printk_ratelimit())
+               printk(KERN_ERR "compat_drm_addmap truncated handle"
+                      " %p for type %d offset %x\n",
+                      handle, m32.type, m32.offset);
 
        if (copy_to_user(argp, &m32, sizeof(m32)))
                return -EFAULT;
index 904d7e9..47db4df 100644 (file)
@@ -96,7 +96,7 @@ int drm_setunique(struct drm_device *dev, void *data,
 {
        struct drm_unique *u = data;
        struct drm_master *master = file_priv->master;
-       int ret;
+       int domain, bus, slot, func, ret;
 
        if (master->unique_len || master->unique)
                return -EBUSY;
@@ -104,12 +104,50 @@ int drm_setunique(struct drm_device *dev, void *data,
        if (!u->unique_len || u->unique_len > 1024)
                return -EINVAL;
 
-       if (!dev->driver->bus->set_unique)
-               return -EINVAL;
+       master->unique_len = u->unique_len;
+       master->unique_size = u->unique_len + 1;
+       master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+       if (!master->unique) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       if (copy_from_user(master->unique, u->unique, master->unique_len)) {
+               ret = -EFAULT;
+               goto err;
+       }
+
+       master->unique[master->unique_len] = '\0';
 
-       ret = dev->driver->bus->set_unique(dev, master, u);
-       if (ret)
+       dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+                              strlen(master->unique) + 2, GFP_KERNEL);
+       if (!dev->devname) {
+               ret = -ENOMEM;
                goto err;
+       }
+
+       sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+               master->unique);
+
+       /* Return error if the busid submitted doesn't match the device's actual
+        * busid.
+        */
+       ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+       if (ret != 3) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       domain = bus >> 8;
+       bus &= 0xff;
+
+       if ((domain != drm_get_pci_domain(dev)) ||
+           (bus != dev->pdev->bus->number) ||
+           (slot != PCI_SLOT(dev->pdev->devfn)) ||
+           (func != PCI_FUNC(dev->pdev->devfn))) {
+               ret = -EINVAL;
+               goto err;
+       }
 
        return 0;
 
@@ -121,15 +159,74 @@ err:
 static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 {
        struct drm_master *master = file_priv->master;
-       int ret;
+       int len, ret;
 
        if (master->unique != NULL)
                drm_unset_busid(dev, master);
 
-       ret = dev->driver->bus->set_busid(dev, master);
-       if (ret)
-               goto err;
+       if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
+               master->unique_len = 10 + strlen(dev->platformdev->name);
+               master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
+
+               if (master->unique == NULL)
+                       return -ENOMEM;
+
+               len = snprintf(master->unique, master->unique_len,
+                       "platform:%s", dev->platformdev->name);
+
+               if (len > master->unique_len) {
+                       DRM_ERROR("Unique buffer overflowed\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               dev->devname =
+                       kmalloc(strlen(dev->platformdev->name) +
+                               master->unique_len + 2, GFP_KERNEL);
+
+               if (dev->devname == NULL) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               sprintf(dev->devname, "%s@%s", dev->platformdev->name,
+                       master->unique);
+
+       } else {
+               master->unique_len = 40;
+               master->unique_size = master->unique_len;
+               master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+               if (master->unique == NULL)
+                       return -ENOMEM;
+
+               len = snprintf(master->unique, master->unique_len,
+                       "pci:%04x:%02x:%02x.%d",
+                       drm_get_pci_domain(dev),
+                       dev->pdev->bus->number,
+                       PCI_SLOT(dev->pdev->devfn),
+                       PCI_FUNC(dev->pdev->devfn));
+               if (len >= master->unique_len) {
+                       DRM_ERROR("buffer overflow");
+                       ret = -EINVAL;
+                       goto err;
+               } else
+                       master->unique_len = len;
+
+               dev->devname =
+                       kmalloc(strlen(dev->driver->pci_driver.name) +
+                               master->unique_len + 2, GFP_KERNEL);
+
+               if (dev->devname == NULL) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+                       master->unique);
+       }
+
        return 0;
+
 err:
        drm_unset_busid(dev, master);
        return ret;
@@ -267,28 +364,6 @@ int drm_getstats(struct drm_device *dev, void *data,
        return 0;
 }
 
-/**
- * Get device/driver capabilities
- */
-int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_get_cap *req = data;
-
-       req->value = 0;
-       switch (req->capability) {
-       case DRM_CAP_DUMB_BUFFER:
-               if (dev->driver->dumb_create)
-                       req->value = 1;
-               break;
-       case DRM_CAP_VBLANK_HIGH_CRTC:
-               req->value = 1;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
 /**
  * Setversion ioctl.
  *
index 3830e9e..16d5155 100644 (file)
 #include <linux/slab.h>
 
 #include <linux/vgaarb.h>
-
-/* Access macro for slots in vblank timestamp ringbuffer. */
-#define vblanktimestamp(dev, crtc, count) ( \
-       (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \
-       ((count) % DRM_VBLANKTIME_RBSIZE)])
-
-/* Retry timestamp calculation up to 3 times to satisfy
- * drm_timestamp_precision before giving up.
- */
-#define DRM_TIMESTAMP_MAXRETRIES 3
-
-/* Threshold in nanoseconds for detection of redundant
- * vblank irq in drm_handle_vblank(). 1 msec should be ok.
- */
-#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
-
 /**
  * Get interrupt from bus id.
  *
@@ -74,96 +58,23 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
 {
        struct drm_irq_busid *p = data;
 
-       if (!dev->driver->bus->irq_by_busid)
+       if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
                return -EINVAL;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
                return -EINVAL;
 
-       return dev->driver->bus->irq_by_busid(dev, p);
-}
-
-/*
- * Clear vblank timestamp buffer for a crtc.
- */
-static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
-{
-       memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0,
-               DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval));
-}
-
-/*
- * Disable vblank irq's on crtc, make sure that last vblank count
- * of hardware and corresponding consistent software vblank counter
- * are preserved, even if there are any spurious vblank irq's after
- * disable.
- */
-static void vblank_disable_and_save(struct drm_device *dev, int crtc)
-{
-       unsigned long irqflags;
-       u32 vblcount;
-       s64 diff_ns;
-       int vblrc;
-       struct timeval tvblank;
-
-       /* Prevent vblank irq processing while disabling vblank irqs,
-        * so no updates of timestamps or count can happen after we've
-        * disabled. Needed to prevent races in case of delayed irq's.
-        * Disable preemption, so vblank_time_lock is held as short as
-        * possible, even under a kernel with PREEMPT_RT patches.
-        */
-       preempt_disable();
-       spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
-
-       dev->driver->disable_vblank(dev, crtc);
-       dev->vblank_enabled[crtc] = 0;
-
-       /* No further vblank irq's will be processed after
-        * this point. Get current hardware vblank count and
-        * vblank timestamp, repeat until they are consistent.
-        *
-        * FIXME: There is still a race condition here and in
-        * drm_update_vblank_count() which can cause off-by-one
-        * reinitialization of software vblank counter. If gpu
-        * vblank counter doesn't increment exactly at the leading
-        * edge of a vblank interval, then we can lose 1 count if
-        * we happen to execute between start of vblank and the
-        * delayed gpu counter increment.
-        */
-       do {
-               dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
-               vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
-       } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc));
+       if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+           (p->busnum & 0xff) != dev->pdev->bus->number ||
+           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
+               return -EINVAL;
 
-       /* Compute time difference to stored timestamp of last vblank
-        * as updated by last invocation of drm_handle_vblank() in vblank irq.
-        */
-       vblcount = atomic_read(&dev->_vblank_count[crtc]);
-       diff_ns = timeval_to_ns(&tvblank) -
-                 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
-
-       /* If there is at least 1 msec difference between the last stored
-        * timestamp and tvblank, then we are currently executing our
-        * disable inside a new vblank interval, the tvblank timestamp
-        * corresponds to this new vblank interval and the irq handler
-        * for this vblank didn't run yet and won't run due to our disable.
-        * Therefore we need to do the job of drm_handle_vblank() and
-        * increment the vblank counter by one to account for this vblank.
-        *
-        * Skip this step if there isn't any high precision timestamp
-        * available. In that case we can't account for this and just
-        * hope for the best.
-        */
-       if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) {
-               atomic_inc(&dev->_vblank_count[crtc]);
-               smp_mb__after_atomic_inc();
-       }
+       p->irq = dev->pdev->irq;
 
-       /* Invalidate all timestamps while vblank irq's are off. */
-       clear_vblank_timestamps(dev, crtc);
+       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+                 p->irq);
 
-       spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-       preempt_enable();
+       return 0;
 }
 
 static void vblank_disable_fn(unsigned long arg)
@@ -180,7 +91,10 @@ static void vblank_disable_fn(unsigned long arg)
                if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
                    dev->vblank_enabled[i]) {
                        DRM_DEBUG("disabling vblank on crtc %d\n", i);
-                       vblank_disable_and_save(dev, i);
+                       dev->last_vblank[i] =
+                               dev->driver->get_vblank_counter(dev, i);
+                       dev->driver->disable_vblank(dev, i);
+                       dev->vblank_enabled[i] = 0;
                }
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
        }
@@ -203,7 +117,6 @@ void drm_vblank_cleanup(struct drm_device *dev)
        kfree(dev->last_vblank);
        kfree(dev->last_vblank_wait);
        kfree(dev->vblank_inmodeset);
-       kfree(dev->_vblank_time);
 
        dev->num_crtcs = 0;
 }
@@ -216,8 +129,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
        setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
                    (unsigned long)dev);
        spin_lock_init(&dev->vbl_lock);
-       spin_lock_init(&dev->vblank_time_lock);
-
        dev->num_crtcs = num_crtcs;
 
        dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
@@ -250,19 +161,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
        if (!dev->vblank_inmodeset)
                goto err;
 
-       dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE,
-                                   sizeof(struct timeval), GFP_KERNEL);
-       if (!dev->_vblank_time)
-               goto err;
-
-       DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
-
-       /* Driver specific high-precision vblank timestamping supported? */
-       if (dev->driver->get_vblank_timestamp)
-               DRM_INFO("Driver supports precise vblank timestamp query.\n");
-       else
-               DRM_INFO("No driver support for vblank timestamp query.\n");
-
        /* Zero per-crtc vblank stuff */
        for (i = 0; i < num_crtcs; i++) {
                init_waitqueue_head(&dev->vbl_queue[i]);
@@ -291,14 +189,11 @@ static void drm_irq_vgaarb_nokms(void *cookie, bool state)
        if (!dev->irq_enabled)
                return;
 
-       if (state) {
-               if (dev->driver->irq_uninstall)
-                       dev->driver->irq_uninstall(dev);
-       } else {
-               if (dev->driver->irq_preinstall)
-                       dev->driver->irq_preinstall(dev);
-               if (dev->driver->irq_postinstall)
-                       dev->driver->irq_postinstall(dev);
+       if (state)
+               dev->driver->irq_uninstall(dev);
+       else {
+               dev->driver->irq_preinstall(dev);
+               dev->driver->irq_postinstall(dev);
        }
 }
 
@@ -341,8 +236,7 @@ int drm_irq_install(struct drm_device *dev)
        DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
 
        /* Before installing handler */
-       if (dev->driver->irq_preinstall)
-               dev->driver->irq_preinstall(dev);
+       dev->driver->irq_preinstall(dev);
 
        /* Install handler */
        if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
@@ -367,16 +261,11 @@ int drm_irq_install(struct drm_device *dev)
                vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
 
        /* After installing handler */
-       if (dev->driver->irq_postinstall)
-               ret = dev->driver->irq_postinstall(dev);
-
+       ret = dev->driver->irq_postinstall(dev);
        if (ret < 0) {
                mutex_lock(&dev->struct_mutex);
                dev->irq_enabled = 0;
                mutex_unlock(&dev->struct_mutex);
-               if (!drm_core_check_feature(dev, DRIVER_MODESET))
-                       vga_client_register(dev->pdev, NULL, NULL, NULL);
-               free_irq(drm_dev_to_irq(dev), dev);
        }
 
        return ret;
@@ -390,7 +279,7 @@ EXPORT_SYMBOL(drm_irq_install);
  *
  * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
  */
-int drm_irq_uninstall(struct drm_device *dev)
+int drm_irq_uninstall(struct drm_device * dev)
 {
        unsigned long irqflags;
        int irq_enabled, i;
@@ -422,8 +311,7 @@ int drm_irq_uninstall(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                vga_client_register(dev->pdev, NULL, NULL, NULL);
 
-       if (dev->driver->irq_uninstall)
-               dev->driver->irq_uninstall(dev);
+       dev->driver->irq_uninstall(dev);
 
        free_irq(drm_dev_to_irq(dev), dev);
 
@@ -447,9 +335,7 @@ int drm_control(struct drm_device *dev, void *data,
 {
        struct drm_control *ctl = data;
 
-       /* if we haven't irq we fallback for compatibility reasons -
-        * this used to be a separate function in drm_dma.h
-        */
+       /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
 
        switch (ctl->func) {
@@ -473,286 +359,6 @@ int drm_control(struct drm_device *dev, void *data,
        }
 }
 
-/**
- * drm_calc_timestamping_constants - Calculate and
- * store various constants which are later needed by
- * vblank and swap-completion timestamping, e.g, by
- * drm_calc_vbltimestamp_from_scanoutpos().
- * They are derived from crtc's true scanout timing,
- * so they take things like panel scaling or other
- * adjustments into account.
- *
- * @crtc drm_crtc whose timestamp constants should be updated.
- *
- */
-void drm_calc_timestamping_constants(struct drm_crtc *crtc)
-{
-       s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
-       u64 dotclock;
-
-       /* Dot clock in Hz: */
-       dotclock = (u64) crtc->hwmode.clock * 1000;
-
-       /* Fields of interlaced scanout modes are only halve a frame duration.
-        * Double the dotclock to get halve the frame-/line-/pixelduration.
-        */
-       if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE)
-               dotclock *= 2;
-
-       /* Valid dotclock? */
-       if (dotclock > 0) {
-               /* Convert scanline length in pixels and video dot clock to
-                * line duration, frame duration and pixel duration in
-                * nanoseconds:
-                */
-               pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
-               linedur_ns  = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
-                                             1000000000), dotclock);
-               framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns;
-       } else
-               DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
-                         crtc->base.id);
-
-       crtc->pixeldur_ns = pixeldur_ns;
-       crtc->linedur_ns  = linedur_ns;
-       crtc->framedur_ns = framedur_ns;
-
-       DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
-                 crtc->base.id, crtc->hwmode.crtc_htotal,
-                 crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay);
-       DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
-                 crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
-                 (int) linedur_ns, (int) pixeldur_ns);
-}
-EXPORT_SYMBOL(drm_calc_timestamping_constants);
-
-/**
- * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms
- * drivers. Implements calculation of exact vblank timestamps from
- * given drm_display_mode timings and current video scanout position
- * of a crtc. This can be called from within get_vblank_timestamp()
- * implementation of a kms driver to implement the actual timestamping.
- *
- * Should return timestamps conforming to the OML_sync_control OpenML
- * extension specification. The timestamp corresponds to the end of
- * the vblank interval, aka start of scanout of topmost-leftmost display
- * pixel in the following video frame.
- *
- * Requires support for optional dev->driver->get_scanout_position()
- * in kms driver, plus a bit of setup code to provide a drm_display_mode
- * that corresponds to the true scanout timing.
- *
- * The current implementation only handles standard video modes. It
- * returns as no operation if a doublescan or interlaced video mode is
- * active. Higher level code is expected to handle this.
- *
- * @dev: DRM device.
- * @crtc: Which crtc's vblank timestamp to retrieve.
- * @max_error: Desired maximum allowable error in timestamps (nanosecs).
- *             On return contains true maximum error of timestamp.
- * @vblank_time: Pointer to struct timeval which should receive the timestamp.
- * @flags: Flags to pass to driver:
- *         0 = Default.
- *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
- * @refcrtc: drm_crtc* of crtc which defines scanout timing.
- *
- * Returns negative value on error, failure or if not supported in current
- * video mode:
- *
- * -EINVAL   - Invalid crtc.
- * -EAGAIN   - Temporary unavailable, e.g., called before initial modeset.
- * -ENOTSUPP - Function not supported in current display mode.
- * -EIO      - Failed, e.g., due to failed scanout position query.
- *
- * Returns or'ed positive status flags on success:
- *
- * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping.
- * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
- *
- */
-int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
-                                         int *max_error,
-                                         struct timeval *vblank_time,
-                                         unsigned flags,
-                                         struct drm_crtc *refcrtc)
-{
-       struct timeval stime, raw_time;
-       struct drm_display_mode *mode;
-       int vbl_status, vtotal, vdisplay;
-       int vpos, hpos, i;
-       s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
-       bool invbl;
-
-       if (crtc < 0 || crtc >= dev->num_crtcs) {
-               DRM_ERROR("Invalid crtc %d\n", crtc);
-               return -EINVAL;
-       }
-
-       /* Scanout position query not supported? Should not happen. */
-       if (!dev->driver->get_scanout_position) {
-               DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
-               return -EIO;
-       }
-
-       mode = &refcrtc->hwmode;
-       vtotal = mode->crtc_vtotal;
-       vdisplay = mode->crtc_vdisplay;
-
-       /* Durations of frames, lines, pixels in nanoseconds. */
-       framedur_ns = refcrtc->framedur_ns;
-       linedur_ns  = refcrtc->linedur_ns;
-       pixeldur_ns = refcrtc->pixeldur_ns;
-
-       /* If mode timing undefined, just return as no-op:
-        * Happens during initial modesetting of a crtc.
-        */
-       if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) {
-               DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
-               return -EAGAIN;
-       }
-
-       /* Get current scanout position with system timestamp.
-        * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
-        * if single query takes longer than max_error nanoseconds.
-        *
-        * This guarantees a tight bound on maximum error if
-        * code gets preempted or delayed for some reason.
-        */
-       for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
-               /* Disable preemption to make it very likely to
-                * succeed in the first iteration even on PREEMPT_RT kernel.
-                */
-               preempt_disable();
-
-               /* Get system timestamp before query. */
-               do_gettimeofday(&stime);
-
-               /* Get vertical and horizontal scanout pos. vpos, hpos. */
-               vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos);
-
-               /* Get system timestamp after query. */
-               do_gettimeofday(&raw_time);
-
-               preempt_enable();
-
-               /* Return as no-op if scanout query unsupported or failed. */
-               if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
-                       DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
-                                 crtc, vbl_status);
-                       return -EIO;
-               }
-
-               duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime);
-
-               /* Accept result with <  max_error nsecs timing uncertainty. */
-               if (duration_ns <= (s64) *max_error)
-                       break;
-       }
-
-       /* Noisy system timing? */
-       if (i == DRM_TIMESTAMP_MAXRETRIES) {
-               DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
-                         crtc, (int) duration_ns/1000, *max_error/1000, i);
-       }
-
-       /* Return upper bound of timestamp precision error. */
-       *max_error = (int) duration_ns;
-
-       /* Check if in vblank area:
-        * vpos is >=0 in video scanout area, but negative
-        * within vblank area, counting down the number of lines until
-        * start of scanout.
-        */
-       invbl = vbl_status & DRM_SCANOUTPOS_INVBL;
-
-       /* Convert scanout position into elapsed time at raw_time query
-        * since start of scanout at first display scanline. delta_ns
-        * can be negative if start of scanout hasn't happened yet.
-        */
-       delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
-
-       /* Is vpos outside nominal vblank area, but less than
-        * 1/100 of a frame height away from start of vblank?
-        * If so, assume this isn't a massively delayed vblank
-        * interrupt, but a vblank interrupt that fired a few
-        * microseconds before true start of vblank. Compensate
-        * by adding a full frame duration to the final timestamp.
-        * Happens, e.g., on ATI R500, R600.
-        *
-        * We only do this if DRM_CALLED_FROM_VBLIRQ.
-        */
-       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
-           ((vdisplay - vpos) < vtotal / 100)) {
-               delta_ns = delta_ns - framedur_ns;
-
-               /* Signal this correction as "applied". */
-               vbl_status |= 0x8;
-       }
-
-       /* Subtract time delta from raw timestamp to get final
-        * vblank_time timestamp for end of vblank.
-        */
-       *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns);
-
-       DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
-                 crtc, (int)vbl_status, hpos, vpos,
-                 (long)raw_time.tv_sec, (long)raw_time.tv_usec,
-                 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
-                 (int)duration_ns/1000, i);
-
-       vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
-       if (invbl)
-               vbl_status |= DRM_VBLANKTIME_INVBL;
-
-       return vbl_status;
-}
-EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
-
-/**
- * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
- * vblank interval.
- *
- * @dev: DRM device
- * @crtc: which crtc's vblank timestamp to retrieve
- * @tvblank: Pointer to target struct timeval which should receive the timestamp
- * @flags: Flags to pass to driver:
- *         0 = Default.
- *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
- *
- * Fetches the system timestamp corresponding to the time of the most recent
- * vblank interval on specified crtc. May call into kms-driver to
- * compute the timestamp with a high-precision GPU specific method.
- *
- * Returns zero if timestamp originates from uncorrected do_gettimeofday()
- * call, i.e., it isn't very precisely locked to the true vblank.
- *
- * Returns non-zero if timestamp is considered to be very precise.
- */
-u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
-                             struct timeval *tvblank, unsigned flags)
-{
-       int ret = 0;
-
-       /* Define requested maximum error on timestamps (nanoseconds). */
-       int max_error = (int) drm_timestamp_precision * 1000;
-
-       /* Query driver if possible and precision timestamping enabled. */
-       if (dev->driver->get_vblank_timestamp && (max_error > 0)) {
-               ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
-                                                       tvblank, flags);
-               if (ret > 0)
-                       return (u32) ret;
-       }
-
-       /* GPU high precision timestamp query unsupported or failed.
-        * Return gettimeofday timestamp as best estimate.
-        */
-       do_gettimeofday(tvblank);
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_get_last_vbltimestamp);
-
 /**
  * drm_vblank_count - retrieve "cooked" vblank counter value
  * @dev: DRM device
@@ -768,40 +374,6 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc)
 }
 EXPORT_SYMBOL(drm_vblank_count);
 
-/**
- * drm_vblank_count_and_time - retrieve "cooked" vblank counter value
- * and the system timestamp corresponding to that vblank counter value.
- *
- * @dev: DRM device
- * @crtc: which counter to retrieve
- * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
- *
- * Fetches the "cooked" vblank count value that represents the number of
- * vblank events since the system was booted, including lost events due to
- * modesetting activity. Returns corresponding system timestamp of the time
- * of the vblank interval that corresponds to the current value vblank counter
- * value.
- */
-u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
-                             struct timeval *vblanktime)
-{
-       u32 cur_vblank;
-
-       /* Read timestamp from slot of _vblank_time ringbuffer
-        * that corresponds to current vblank count. Retry if
-        * count has incremented during readout. This works like
-        * a seqlock.
-        */
-       do {
-               cur_vblank = atomic_read(&dev->_vblank_count[crtc]);
-               *vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
-               smp_rmb();
-       } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc]));
-
-       return cur_vblank;
-}
-EXPORT_SYMBOL(drm_vblank_count_and_time);
-
 /**
  * drm_update_vblank_count - update the master vblank counter
  * @dev: DRM device
@@ -820,8 +392,7 @@ EXPORT_SYMBOL(drm_vblank_count_and_time);
  */
 static void drm_update_vblank_count(struct drm_device *dev, int crtc)
 {
-       u32 cur_vblank, diff, tslot, rc;
-       struct timeval t_vblank;
+       u32 cur_vblank, diff;
 
        /*
         * Interrupts were disabled prior to this call, so deal with counter
@@ -829,18 +400,8 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
         * NOTE!  It's possible we lost a full dev->max_vblank_count events
         * here if the register is small or we had vblank interrupts off for
         * a long time.
-        *
-        * We repeat the hardware vblank counter & timestamp query until
-        * we get consistent results. This to prevent races between gpu
-        * updating its hardware counter while we are retrieving the
-        * corresponding vblank timestamp.
         */
-       do {
-               cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
-               rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
-       } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
-
-       /* Deal with counter wrap */
+       cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
        diff = cur_vblank - dev->last_vblank[crtc];
        if (cur_vblank < dev->last_vblank[crtc]) {
                diff += dev->max_vblank_count;
@@ -852,18 +413,7 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
        DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
                  crtc, diff);
 
-       /* Reinitialize corresponding vblank timestamp if high-precision query
-        * available. Skip this step if query unsupported or failed. Will
-        * reinitialize delayed at next vblank interrupt in that case.
-        */
-       if (rc) {
-               tslot = atomic_read(&dev->_vblank_count[crtc]) + diff;
-               vblanktimestamp(dev, crtc, tslot) = t_vblank;
-       }
-
-       smp_mb__before_atomic_inc();
        atomic_add(diff, &dev->_vblank_count[crtc]);
-       smp_mb__after_atomic_inc();
 }
 
 /**
@@ -879,27 +429,15 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
  */
 int drm_vblank_get(struct drm_device *dev, int crtc)
 {
-       unsigned long irqflags, irqflags2;
+       unsigned long irqflags;
        int ret = 0;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        /* Going from 0->1 means we have to enable interrupts again */
        if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
-               /* Disable preemption while holding vblank_time_lock. Do
-                * it explicitely to guard against PREEMPT_RT kernel.
-                */
-               preempt_disable();
-               spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
                if (!dev->vblank_enabled[crtc]) {
-                       /* Enable vblank irqs under vblank_time_lock protection.
-                        * All vblank count & timestamp updates are held off
-                        * until we are done reinitializing master counter and
-                        * timestamps. Filtercode in drm_handle_vblank() will
-                        * prevent double-accounting of same vblank interval.
-                        */
                        ret = dev->driver->enable_vblank(dev, crtc);
-                       DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n",
-                                 crtc, ret);
+                       DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
                        if (ret)
                                atomic_dec(&dev->vblank_refcount[crtc]);
                        else {
@@ -907,8 +445,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
                                drm_update_vblank_count(dev, crtc);
                        }
                }
-               spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
-               preempt_enable();
        } else {
                if (!dev->vblank_enabled[crtc]) {
                        atomic_dec(&dev->vblank_refcount[crtc]);
@@ -927,50 +463,27 @@ EXPORT_SYMBOL(drm_vblank_get);
  * @crtc: which counter to give up
  *
  * Release ownership of a given vblank counter, turning off interrupts
- * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
+ * if possible.
  */
 void drm_vblank_put(struct drm_device *dev, int crtc)
 {
-       BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0);
+       BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
 
        /* Last user schedules interrupt disable */
-       if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) &&
-           (drm_vblank_offdelay > 0))
-               mod_timer(&dev->vblank_disable_timer,
-                         jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
+       if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
+               mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
        unsigned long irqflags;
-       unsigned int seq;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
-       vblank_disable_and_save(dev, crtc);
+       dev->driver->disable_vblank(dev, crtc);
        DRM_WAKEUP(&dev->vbl_queue[crtc]);
-
-       /* Send any queued vblank events, lest the natives grow disquiet */
-       seq = drm_vblank_count_and_time(dev, crtc, &now);
-       list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
-               if (e->pipe != crtc)
-                       continue;
-               DRM_DEBUG("Sending premature vblank event on disable: \
-                         wanted %d, current %d\n",
-                         e->event.sequence, seq);
-
-               e->event.sequence = seq;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               drm_vblank_put(dev, e->pipe);
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-                                                e->event.sequence);
-       }
-
+       dev->vblank_enabled[crtc] = 0;
+       dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
@@ -1036,8 +549,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
                    struct drm_file *file_priv)
 {
        struct drm_modeset_ctl *modeset = data;
-       int ret = 0;
-       unsigned int crtc;
+       int crtc, ret = 0;
 
        /* If drm_vblank_init() hasn't been called yet, just no-op */
        if (!dev->num_crtcs)
@@ -1090,6 +602,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        e->base.file_priv = file_priv;
        e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
 
+       do_gettimeofday(&now);
        spin_lock_irqsave(&dev->event_lock, flags);
 
        if (file_priv->event_space < sizeof e->event) {
@@ -1098,8 +611,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        }
 
        file_priv->event_space -= sizeof e->event;
-       seq = drm_vblank_count_and_time(dev, pipe, &now);
-
+       seq = drm_vblank_count(dev, pipe);
        if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
            (seq - vblwait->request.sequence) <= (1 << 23)) {
                vblwait->request.sequence = seq + 1;
@@ -1114,18 +626,15 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 
        e->event.sequence = vblwait->request.sequence;
        if ((seq - vblwait->request.sequence) <= (1 << 23)) {
-               e->event.sequence = seq;
                e->event.tv_sec = now.tv_sec;
                e->event.tv_usec = now.tv_usec;
                drm_vblank_put(dev, pipe);
                list_add_tail(&e->base.link, &e->base.file_priv->event_list);
                wake_up_interruptible(&e->base.file_priv->event_wait);
-               vblwait->reply.sequence = seq;
                trace_drm_vblank_event_delivered(current->pid, pipe,
                                                 vblwait->request.sequence);
        } else {
                list_add_tail(&e->base.link, &dev->vblank_event_list);
-               vblwait->reply.sequence = vblwait->request.sequence;
        }
 
        spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -1159,7 +668,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
 {
        union drm_wait_vblank *vblwait = data;
        int ret = 0;
-       unsigned int flags, seq, crtc, high_crtc;
+       unsigned int flags, seq, crtc;
 
        if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
                return -EINVAL;
@@ -1168,21 +677,16 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
                return -EINVAL;
 
        if (vblwait->request.type &
-           ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
-             _DRM_VBLANK_HIGH_CRTC_MASK)) {
+           ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
                DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
                          vblwait->request.type,
-                         (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
-                          _DRM_VBLANK_HIGH_CRTC_MASK));
+                         (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
                return -EINVAL;
        }
 
        flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-       high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
-       if (high_crtc)
-               crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
-       else
-               crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+       crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+
        if (crtc >= dev->num_crtcs)
                return -EINVAL;
 
@@ -1223,10 +727,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        if (ret != -EINTR) {
                struct timeval now;
 
-               vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now);
+               do_gettimeofday(&now);
+
                vblwait->reply.tval_sec = now.tv_sec;
                vblwait->reply.tval_usec = now.tv_usec;
-
+               vblwait->reply.sequence = drm_vblank_count(dev, crtc);
                DRM_DEBUG("returning %d to client\n",
                          vblwait->reply.sequence);
        } else {
@@ -1245,7 +750,8 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
        unsigned long flags;
        unsigned int seq;
 
-       seq = drm_vblank_count_and_time(dev, crtc, &now);
+       do_gettimeofday(&now);
+       seq = drm_vblank_count(dev, crtc);
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
@@ -1281,68 +787,13 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
  * Drivers should call this routine in their vblank interrupt handlers to
  * update the vblank counter and send any signals that may be pending.
  */
-bool drm_handle_vblank(struct drm_device *dev, int crtc)
+void drm_handle_vblank(struct drm_device *dev, int crtc)
 {
-       u32 vblcount;
-       s64 diff_ns;
-       struct timeval tvblank;
-       unsigned long irqflags;
-
        if (!dev->num_crtcs)
-               return false;
-
-       /* Need timestamp lock to prevent concurrent execution with
-        * vblank enable/disable, as this would cause inconsistent
-        * or corrupted timestamps and vblank counts.
-        */
-       spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
-
-       /* Vblank irq handling disabled. Nothing to do. */
-       if (!dev->vblank_enabled[crtc]) {
-               spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-               return false;
-       }
-
-       /* Fetch corresponding timestamp for this vblank interval from
-        * driver and store it in proper slot of timestamp ringbuffer.
-        */
-
-       /* Get current timestamp and count. */
-       vblcount = atomic_read(&dev->_vblank_count[crtc]);
-       drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
-
-       /* Compute time difference to timestamp of last vblank */
-       diff_ns = timeval_to_ns(&tvblank) -
-                 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
-
-       /* Update vblank timestamp and count if at least
-        * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
-        * difference between last stored timestamp and current
-        * timestamp. A smaller difference means basically
-        * identical timestamps. Happens if this vblank has
-        * been already processed and this is a redundant call,
-        * e.g., due to spurious vblank interrupts. We need to
-        * ignore those for accounting.
-        */
-       if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) {
-               /* Store new timestamp in ringbuffer. */
-               vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
-
-               /* Increment cooked vblank count. This also atomically commits
-                * the timestamp computed above.
-                */
-               smp_mb__before_atomic_inc();
-               atomic_inc(&dev->_vblank_count[crtc]);
-               smp_mb__after_atomic_inc();
-       } else {
-               DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
-                         crtc, (int) diff_ns);
-       }
+               return;
 
+       atomic_inc(&dev->_vblank_count[crtc]);
        DRM_WAKEUP(&dev->vbl_queue[crtc]);
        drm_handle_vblank_events(dev, crtc);
-
-       spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-       return true;
 }
 EXPORT_SYMBOL(drm_handle_vblank);
index 959186c..a6bfc30 100644 (file)
@@ -64,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
                else {
                        child =
                            list_entry(mm->unused_nodes.next,
-                                      struct drm_mm_node, node_list);
-                       list_del(&child->node_list);
+                                      struct drm_mm_node, free_stack);
+                       list_del(&child->free_stack);
                        --mm->num_unused;
                }
                spin_unlock(&mm->unused_lock);
@@ -94,242 +94,195 @@ int drm_mm_pre_get(struct drm_mm *mm)
                        return ret;
                }
                ++mm->num_unused;
-               list_add_tail(&node->node_list, &mm->unused_nodes);
+               list_add_tail(&node->free_stack, &mm->unused_nodes);
        }
        spin_unlock(&mm->unused_lock);
        return 0;
 }
 EXPORT_SYMBOL(drm_mm_pre_get);
 
-static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
+static int drm_mm_create_tail_node(struct drm_mm *mm,
+                                  unsigned long start,
+                                  unsigned long size, int atomic)
 {
-       return hole_node->start + hole_node->size;
-}
+       struct drm_mm_node *child;
 
-static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
-{
-       struct drm_mm_node *next_node =
-               list_entry(hole_node->node_list.next, struct drm_mm_node,
-                          node_list);
+       child = drm_mm_kmalloc(mm, atomic);
+       if (unlikely(child == NULL))
+               return -ENOMEM;
 
-       return next_node->start;
-}
+       child->free = 1;
+       child->size = size;
+       child->start = start;
+       child->mm = mm;
 
-static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
-                                struct drm_mm_node *node,
-                                unsigned long size, unsigned alignment)
-{
-       struct drm_mm *mm = hole_node->mm;
-       unsigned long tmp = 0, wasted = 0;
-       unsigned long hole_start = drm_mm_hole_node_start(hole_node);
-       unsigned long hole_end = drm_mm_hole_node_end(hole_node);
+       list_add_tail(&child->node_list, &mm->node_list);
+       list_add_tail(&child->free_stack, &mm->free_stack);
 
-       BUG_ON(!hole_node->hole_follows || node->allocated);
+       return 0;
+}
 
-       if (alignment)
-               tmp = hole_start % alignment;
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
+                                                unsigned long size,
+                                                int atomic)
+{
+       struct drm_mm_node *child;
 
-       if (!tmp) {
-               hole_node->hole_follows = 0;
-               list_del_init(&hole_node->hole_stack);
-       } else
-               wasted = alignment - tmp;
+       child = drm_mm_kmalloc(parent->mm, atomic);
+       if (unlikely(child == NULL))
+               return NULL;
 
-       node->start = hole_start + wasted;
-       node->size = size;
-       node->mm = mm;
-       node->allocated = 1;
+       INIT_LIST_HEAD(&child->free_stack);
 
-       INIT_LIST_HEAD(&node->hole_stack);
-       list_add(&node->node_list, &hole_node->node_list);
+       child->size = size;
+       child->start = parent->start;
+       child->mm = parent->mm;
 
-       BUG_ON(node->start + node->size > hole_end);
+       list_add_tail(&child->node_list, &parent->node_list);
+       INIT_LIST_HEAD(&child->free_stack);
 
-       if (node->start + node->size < hole_end) {
-               list_add(&node->hole_stack, &mm->hole_stack);
-               node->hole_follows = 1;
-       } else {
-               node->hole_follows = 0;
-       }
+       parent->size -= size;
+       parent->start += size;
+       return child;
 }
 
-struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
+
+struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
                                             unsigned long size,
                                             unsigned alignment,
                                             int atomic)
 {
-       struct drm_mm_node *node;
-
-       node = drm_mm_kmalloc(hole_node->mm, atomic);
-       if (unlikely(node == NULL))
-               return NULL;
 
-       drm_mm_insert_helper(hole_node, node, size, alignment);
+       struct drm_mm_node *align_splitoff = NULL;
+       unsigned tmp = 0;
 
-       return node;
-}
-EXPORT_SYMBOL(drm_mm_get_block_generic);
+       if (alignment)
+               tmp = node->start % alignment;
 
-/**
- * Search for free space and insert a preallocated memory node. Returns
- * -ENOSPC if no suitable free area is available. The preallocated memory node
- * must be cleared.
- */
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-                      unsigned long size, unsigned alignment)
-{
-       struct drm_mm_node *hole_node;
+       if (tmp) {
+               align_splitoff =
+                   drm_mm_split_at_start(node, alignment - tmp, atomic);
+               if (unlikely(align_splitoff == NULL))
+                       return NULL;
+       }
 
-       hole_node = drm_mm_search_free(mm, size, alignment, 0);
-       if (!hole_node)
-               return -ENOSPC;
+       if (node->size == size) {
+               list_del_init(&node->free_stack);
+               node->free = 0;
+       } else {
+               node = drm_mm_split_at_start(node, size, atomic);
+       }
 
-       drm_mm_insert_helper(hole_node, node, size, alignment);
+       if (align_splitoff)
+               drm_mm_put_block(align_splitoff);
 
-       return 0;
+       return node;
 }
-EXPORT_SYMBOL(drm_mm_insert_node);
+EXPORT_SYMBOL(drm_mm_get_block_generic);
 
-static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
-                                      struct drm_mm_node *node,
-                                      unsigned long size, unsigned alignment,
-                                      unsigned long start, unsigned long end)
+struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
+                                               unsigned long size,
+                                               unsigned alignment,
+                                               unsigned long start,
+                                               unsigned long end,
+                                               int atomic)
 {
-       struct drm_mm *mm = hole_node->mm;
-       unsigned long tmp = 0, wasted = 0;
-       unsigned long hole_start = drm_mm_hole_node_start(hole_node);
-       unsigned long hole_end = drm_mm_hole_node_end(hole_node);
-
-       BUG_ON(!hole_node->hole_follows || node->allocated);
+       struct drm_mm_node *align_splitoff = NULL;
+       unsigned tmp = 0;
+       unsigned wasted = 0;
 
-       if (hole_start < start)
-               wasted += start - hole_start;
+       if (node->start < start)
+               wasted += start - node->start;
        if (alignment)
-               tmp = (hole_start + wasted) % alignment;
+               tmp = ((node->start + wasted) % alignment);
 
        if (tmp)
                wasted += alignment - tmp;
-
-       if (!wasted) {
-               hole_node->hole_follows = 0;
-               list_del_init(&hole_node->hole_stack);
+       if (wasted) {
+               align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
+               if (unlikely(align_splitoff == NULL))
+                       return NULL;
        }
 
-       node->start = hole_start + wasted;
-       node->size = size;
-       node->mm = mm;
-       node->allocated = 1;
-
-       INIT_LIST_HEAD(&node->hole_stack);
-       list_add(&node->node_list, &hole_node->node_list);
-
-       BUG_ON(node->start + node->size > hole_end);
-       BUG_ON(node->start + node->size > end);
-
-       if (node->start + node->size < hole_end) {
-               list_add(&node->hole_stack, &mm->hole_stack);
-               node->hole_follows = 1;
+       if (node->size == size) {
+               list_del_init(&node->free_stack);
+               node->free = 0;
        } else {
-               node->hole_follows = 0;
+               node = drm_mm_split_at_start(node, size, atomic);
        }
-}
-
-struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
-                                               unsigned long size,
-                                               unsigned alignment,
-                                               unsigned long start,
-                                               unsigned long end,
-                                               int atomic)
-{
-       struct drm_mm_node *node;
 
-       node = drm_mm_kmalloc(hole_node->mm, atomic);
-       if (unlikely(node == NULL))
-               return NULL;
-
-       drm_mm_insert_helper_range(hole_node, node, size, alignment,
-                                  start, end);
+       if (align_splitoff)
+               drm_mm_put_block(align_splitoff);
 
        return node;
 }
 EXPORT_SYMBOL(drm_mm_get_block_range_generic);
 
-/**
- * Search for free space and insert a preallocated memory node. Returns
- * -ENOSPC if no suitable free area is available. This is for range
- * restricted allocations. The preallocated memory node must be cleared.
+/*
+ * Put a block. Merge with the previous and / or next block if they are free.
+ * Otherwise add to the free stack.
  */
-int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
-                               unsigned long size, unsigned alignment,
-                               unsigned long start, unsigned long end)
-{
-       struct drm_mm_node *hole_node;
 
-       hole_node = drm_mm_search_free_in_range(mm, size, alignment,
-                                               start, end, 0);
-       if (!hole_node)
-               return -ENOSPC;
-
-       drm_mm_insert_helper_range(hole_node, node, size, alignment,
-                                  start, end);
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_mm_insert_node_in_range);
-
-/**
- * Remove a memory node from the allocator.
- */
-void drm_mm_remove_node(struct drm_mm_node *node)
+void drm_mm_put_block(struct drm_mm_node *cur)
 {
-       struct drm_mm *mm = node->mm;
-       struct drm_mm_node *prev_node;
-
-       BUG_ON(node->scanned_block || node->scanned_prev_free
-                                  || node->scanned_next_free);
-
-       prev_node =
-           list_entry(node->node_list.prev, struct drm_mm_node, node_list);
-
-       if (node->hole_follows) {
-               BUG_ON(drm_mm_hole_node_start(node)
-                               == drm_mm_hole_node_end(node));
-               list_del(&node->hole_stack);
-       } else
-               BUG_ON(drm_mm_hole_node_start(node)
-                               != drm_mm_hole_node_end(node));
-
-       if (!prev_node->hole_follows) {
-               prev_node->hole_follows = 1;
-               list_add(&prev_node->hole_stack, &mm->hole_stack);
-       } else
-               list_move(&prev_node->hole_stack, &mm->hole_stack);
-
-       list_del(&node->node_list);
-       node->allocated = 0;
-}
-EXPORT_SYMBOL(drm_mm_remove_node);
 
-/*
- * Remove a memory node from the allocator and free the allocated struct
- * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
- * drm_mm_get_block functions.
- */
-void drm_mm_put_block(struct drm_mm_node *node)
-{
+       struct drm_mm *mm = cur->mm;
+       struct list_head *cur_head = &cur->node_list;
+       struct list_head *root_head = &mm->node_list;
+       struct drm_mm_node *prev_node = NULL;
+       struct drm_mm_node *next_node;
 
-       struct drm_mm *mm = node->mm;
+       int merged = 0;
 
-       drm_mm_remove_node(node);
+       BUG_ON(cur->scanned_block || cur->scanned_prev_free
+                                 || cur->scanned_next_free);
 
-       spin_lock(&mm->unused_lock);
-       if (mm->num_unused < MM_UNUSED_TARGET) {
-               list_add(&node->node_list, &mm->unused_nodes);
-               ++mm->num_unused;
-       } else
-               kfree(node);
-       spin_unlock(&mm->unused_lock);
+       if (cur_head->prev != root_head) {
+               prev_node =
+                   list_entry(cur_head->prev, struct drm_mm_node, node_list);
+               if (prev_node->free) {
+                       prev_node->size += cur->size;
+                       merged = 1;
+               }
+       }
+       if (cur_head->next != root_head) {
+               next_node =
+                   list_entry(cur_head->next, struct drm_mm_node, node_list);
+               if (next_node->free) {
+                       if (merged) {
+                               prev_node->size += next_node->size;
+                               list_del(&next_node->node_list);
+                               list_del(&next_node->free_stack);
+                               spin_lock(&mm->unused_lock);
+                               if (mm->num_unused < MM_UNUSED_TARGET) {
+                                       list_add(&next_node->free_stack,
+                                                &mm->unused_nodes);
+                                       ++mm->num_unused;
+                               } else
+                                       kfree(next_node);
+                               spin_unlock(&mm->unused_lock);
+                       } else {
+                               next_node->size += cur->size;
+                               next_node->start = cur->start;
+                               merged = 1;
+                       }
+               }
+       }
+       if (!merged) {
+               cur->free = 1;
+               list_add(&cur->free_stack, &mm->free_stack);
+       } else {
+               list_del(&cur->node_list);
+               spin_lock(&mm->unused_lock);
+               if (mm->num_unused < MM_UNUSED_TARGET) {
+                       list_add(&cur->free_stack, &mm->unused_nodes);
+                       ++mm->num_unused;
+               } else
+                       kfree(cur);
+               spin_unlock(&mm->unused_lock);
+       }
 }
+
 EXPORT_SYMBOL(drm_mm_put_block);
 
 static int check_free_hole(unsigned long start, unsigned long end,
@@ -366,10 +319,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
        best = NULL;
        best_size = ~0UL;
 
-       list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
-               BUG_ON(!entry->hole_follows);
-               if (!check_free_hole(drm_mm_hole_node_start(entry),
-                                    drm_mm_hole_node_end(entry),
+       list_for_each_entry(entry, &mm->free_stack, free_stack) {
+               if (!check_free_hole(entry->start, entry->start + entry->size,
                                     size, alignment))
                        continue;
 
@@ -402,13 +353,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
        best = NULL;
        best_size = ~0UL;
 
-       list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
-               unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
-                       start : drm_mm_hole_node_start(entry);
-               unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
-                       end : drm_mm_hole_node_end(entry);
+       list_for_each_entry(entry, &mm->free_stack, free_stack) {
+               unsigned long adj_start = entry->start < start ?
+                       start : entry->start;
+               unsigned long adj_end = entry->start + entry->size > end ?
+                       end : entry->start + entry->size;
 
-               BUG_ON(!entry->hole_follows);
                if (!check_free_hole(adj_start, adj_end, size, alignment))
                        continue;
 
@@ -425,23 +375,6 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
 }
 EXPORT_SYMBOL(drm_mm_search_free_in_range);
 
-/**
- * Moves an allocation. To be used with embedded struct drm_mm_node.
- */
-void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
-{
-       list_replace(&old->node_list, &new->node_list);
-       list_replace(&old->hole_stack, &new->hole_stack);
-       new->hole_follows = old->hole_follows;
-       new->mm = old->mm;
-       new->start = old->start;
-       new->size = old->size;
-
-       old->allocated = 0;
-       new->allocated = 1;
-}
-EXPORT_SYMBOL(drm_mm_replace_node);
-
 /**
  * Initializa lru scanning.
  *
@@ -459,37 +392,9 @@ void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
        mm->scanned_blocks = 0;
        mm->scan_hit_start = 0;
        mm->scan_hit_size = 0;
-       mm->scan_check_range = 0;
-       mm->prev_scanned_node = NULL;
 }
 EXPORT_SYMBOL(drm_mm_init_scan);
 
-/**
- * Initializa lru scanning.
- *
- * This simply sets up the scanning routines with the parameters for the desired
- * hole. This version is for range-restricted scans.
- *
- * Warning: As long as the scan list is non-empty, no other operations than
- * adding/removing nodes to/from the scan list are allowed.
- */
-void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
-                                unsigned alignment,
-                                unsigned long start,
-                                unsigned long end)
-{
-       mm->scan_alignment = alignment;
-       mm->scan_size = size;
-       mm->scanned_blocks = 0;
-       mm->scan_hit_start = 0;
-       mm->scan_hit_size = 0;
-       mm->scan_start = start;
-       mm->scan_end = end;
-       mm->scan_check_range = 1;
-       mm->prev_scanned_node = NULL;
-}
-EXPORT_SYMBOL(drm_mm_init_scan_with_range);
-
 /**
  * Add a node to the scan list that might be freed to make space for the desired
  * hole.
@@ -499,42 +404,58 @@ EXPORT_SYMBOL(drm_mm_init_scan_with_range);
 int drm_mm_scan_add_block(struct drm_mm_node *node)
 {
        struct drm_mm *mm = node->mm;
-       struct drm_mm_node *prev_node;
-       unsigned long hole_start, hole_end;
-       unsigned long adj_start;
-       unsigned long adj_end;
+       struct list_head *prev_free, *next_free;
+       struct drm_mm_node *prev_node, *next_node;
 
        mm->scanned_blocks++;
 
-       BUG_ON(node->scanned_block);
+       prev_free = next_free = NULL;
+
+       BUG_ON(node->free);
        node->scanned_block = 1;
+       node->free = 1;
 
-       prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
-                              node_list);
-
-       node->scanned_preceeds_hole = prev_node->hole_follows;
-       prev_node->hole_follows = 1;
-       list_del(&node->node_list);
-       node->node_list.prev = &prev_node->node_list;
-       node->node_list.next = &mm->prev_scanned_node->node_list;
-       mm->prev_scanned_node = node;
-
-       hole_start = drm_mm_hole_node_start(prev_node);
-       hole_end = drm_mm_hole_node_end(prev_node);
-       if (mm->scan_check_range) {
-               adj_start = hole_start < mm->scan_start ?
-                       mm->scan_start : hole_start;
-               adj_end = hole_end > mm->scan_end ?
-                       mm->scan_end : hole_end;
-       } else {
-               adj_start = hole_start;
-               adj_end = hole_end;
+       if (node->node_list.prev != &mm->node_list) {
+               prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+                                      node_list);
+
+               if (prev_node->free) {
+                       list_del(&prev_node->node_list);
+
+                       node->start = prev_node->start;
+                       node->size += prev_node->size;
+
+                       prev_node->scanned_prev_free = 1;
+
+                       prev_free = &prev_node->free_stack;
+               }
        }
 
-       if (check_free_hole(adj_start , adj_end,
+       if (node->node_list.next != &mm->node_list) {
+               next_node = list_entry(node->node_list.next, struct drm_mm_node,
+                                      node_list);
+
+               if (next_node->free) {
+                       list_del(&next_node->node_list);
+
+                       node->size += next_node->size;
+
+                       next_node->scanned_next_free = 1;
+
+                       next_free = &next_node->free_stack;
+               }
+       }
+
+       /* The free_stack list is not used for allocated objects, so these two
+        * pointers can be abused (as long as no allocations in this memory
+        * manager happens). */
+       node->free_stack.prev = prev_free;
+       node->free_stack.next = next_free;
+
+       if (check_free_hole(node->start, node->start + node->size,
                            mm->scan_size, mm->scan_alignment)) {
-               mm->scan_hit_start = hole_start;
-               mm->scan_hit_size = hole_end;
+               mm->scan_hit_start = node->start;
+               mm->scan_hit_size = node->size;
 
                return 1;
        }
@@ -551,7 +472,7 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
  * corrupted.
  *
  * When the scan list is empty, the selected memory nodes can be freed. An
- * immediately following drm_mm_search_free with best_match = 0 will then return
+ * immediatly following drm_mm_search_free with best_match = 0 will then return
  * the just freed block (because its at the top of the free_stack list).
  *
  * Returns one if this block should be evicted, zero otherwise. Will always
@@ -560,19 +481,39 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
 int drm_mm_scan_remove_block(struct drm_mm_node *node)
 {
        struct drm_mm *mm = node->mm;
-       struct drm_mm_node *prev_node;
+       struct drm_mm_node *prev_node, *next_node;
 
        mm->scanned_blocks--;
 
        BUG_ON(!node->scanned_block);
        node->scanned_block = 0;
+       node->free = 0;
 
-       prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
-                              node_list);
+       prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
+                              free_stack);
+       next_node = list_entry(node->free_stack.next, struct drm_mm_node,
+                              free_stack);
 
-       prev_node->hole_follows = node->scanned_preceeds_hole;
-       INIT_LIST_HEAD(&node->node_list);
-       list_add(&node->node_list, &prev_node->node_list);
+       if (prev_node) {
+               BUG_ON(!prev_node->scanned_prev_free);
+               prev_node->scanned_prev_free = 0;
+
+               list_add_tail(&prev_node->node_list, &node->node_list);
+
+               node->start = prev_node->start + prev_node->size;
+               node->size -= prev_node->size;
+       }
+
+       if (next_node) {
+               BUG_ON(!next_node->scanned_next_free);
+               next_node->scanned_next_free = 0;
+
+               list_add(&next_node->node_list, &node->node_list);
+
+               node->size -= next_node->size;
+       }
+
+       INIT_LIST_HEAD(&node->free_stack);
 
        /* Only need to check for containement because start&size for the
         * complete resulting free block (not just the desired part) is
@@ -589,7 +530,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block);
 
 int drm_mm_clean(struct drm_mm * mm)
 {
-       struct list_head *head = &mm->head_node.node_list;
+       struct list_head *head = &mm->node_list;
 
        return (head->next->next == head);
 }
@@ -597,40 +538,38 @@ EXPORT_SYMBOL(drm_mm_clean);
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
-       INIT_LIST_HEAD(&mm->hole_stack);
+       INIT_LIST_HEAD(&mm->node_list);
+       INIT_LIST_HEAD(&mm->free_stack);
        INIT_LIST_HEAD(&mm->unused_nodes);
        mm->num_unused = 0;
        mm->scanned_blocks = 0;
        spin_lock_init(&mm->unused_lock);
 
-       /* Clever trick to avoid a special case in the free hole tracking. */
-       INIT_LIST_HEAD(&mm->head_node.node_list);
-       INIT_LIST_HEAD(&mm->head_node.hole_stack);
-       mm->head_node.hole_follows = 1;
-       mm->head_node.scanned_block = 0;
-       mm->head_node.scanned_prev_free = 0;
-       mm->head_node.scanned_next_free = 0;
-       mm->head_node.mm = mm;
-       mm->head_node.start = start + size;
-       mm->head_node.size = start - mm->head_node.start;
-       list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
-
-       return 0;
+       return drm_mm_create_tail_node(mm, start, size, 0);
 }
 EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(struct drm_mm * mm)
 {
-       struct drm_mm_node *entry, *next;
+       struct list_head *bnode = mm->free_stack.next;
+       struct drm_mm_node *entry;
+       struct drm_mm_node *next;
+
+       entry = list_entry(bnode, struct drm_mm_node, free_stack);
 
-       if (!list_empty(&mm->head_node.node_list)) {
+       if (entry->node_list.next != &mm->node_list ||
+           entry->free_stack.next != &mm->free_stack) {
                DRM_ERROR("Memory manager not clean. Delaying takedown\n");
                return;
        }
 
+       list_del(&entry->free_stack);
+       list_del(&entry->node_list);
+       kfree(entry);
+
        spin_lock(&mm->unused_lock);
-       list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
-               list_del(&entry->node_list);
+       list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
+               list_del(&entry->free_stack);
                kfree(entry);
                --mm->num_unused;
        }
@@ -643,37 +582,19 @@ EXPORT_SYMBOL(drm_mm_takedown);
 void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 {
        struct drm_mm_node *entry;
-       unsigned long total_used = 0, total_free = 0, total = 0;
-       unsigned long hole_start, hole_end, hole_size;
-
-       hole_start = drm_mm_hole_node_start(&mm->head_node);
-       hole_end = drm_mm_hole_node_end(&mm->head_node);
-       hole_size = hole_end - hole_start;
-       if (hole_size)
-               printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
-                       prefix, hole_start, hole_end,
-                       hole_size);
-       total_free += hole_size;
-
-       drm_mm_for_each_node(entry, mm) {
-               printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
+       int total_used = 0, total_free = 0, total = 0;
+
+       list_for_each_entry(entry, &mm->node_list, node_list) {
+               printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
                        prefix, entry->start, entry->start + entry->size,
-                       entry->size);
-               total_used += entry->size;
-
-               if (entry->hole_follows) {
-                       hole_start = drm_mm_hole_node_start(entry);
-                       hole_end = drm_mm_hole_node_end(entry);
-                       hole_size = hole_end - hole_start;
-                       printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
-                               prefix, hole_start, hole_end,
-                               hole_size);
-                       total_free += hole_size;
-               }
+                       entry->size, entry->free ? "free" : "used");
+               total += entry->size;
+               if (entry->free)
+                       total_free += entry->size;
+               else
+                       total_used += entry->size;
        }
-       total = total_free + total_used;
-
-       printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
+       printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
                total_used, total_free);
 }
 EXPORT_SYMBOL(drm_mm_debug_table);
@@ -682,34 +603,17 @@ EXPORT_SYMBOL(drm_mm_debug_table);
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 {
        struct drm_mm_node *entry;
-       unsigned long total_used = 0, total_free = 0, total = 0;
-       unsigned long hole_start, hole_end, hole_size;
-
-       hole_start = drm_mm_hole_node_start(&mm->head_node);
-       hole_end = drm_mm_hole_node_end(&mm->head_node);
-       hole_size = hole_end - hole_start;
-       if (hole_size)
-               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
-                               hole_start, hole_end, hole_size);
-       total_free += hole_size;
-
-       drm_mm_for_each_node(entry, mm) {
-               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
-                               entry->start, entry->start + entry->size,
-                               entry->size);
-               total_used += entry->size;
-               if (entry->hole_follows) {
-                       hole_start = drm_mm_hole_node_start(entry);
-                       hole_end = drm_mm_hole_node_end(entry);
-                       hole_size = hole_end - hole_start;
-                       seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
-                                       hole_start, hole_end, hole_size);
-                       total_free += hole_size;
-               }
+       int total_used = 0, total_free = 0, total = 0;
+
+       list_for_each_entry(entry, &mm->node_list, node_list) {
+               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
+               total += entry->size;
+               if (entry->free)
+                       total_free += entry->size;
+               else
+                       total_used += entry->size;
        }
-       total = total_free + total_used;
-
-       seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
+       seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
        return 0;
 }
 EXPORT_SYMBOL(drm_mm_dump_table);
index ad74fb4..58e65f9 100644 (file)
@@ -593,7 +593,7 @@ EXPORT_SYMBOL(drm_mode_height);
  *
  * Return @modes's hsync rate in kHz, rounded to the nearest int.
  */
-int drm_mode_hsync(const struct drm_display_mode *mode)
+int drm_mode_hsync(struct drm_display_mode *mode)
 {
        unsigned int calc_val;
 
@@ -627,7 +627,7 @@ EXPORT_SYMBOL(drm_mode_hsync);
  * If it is 70.288, it will return 70Hz.
  * If it is 59.6, it will return 60Hz.
  */
-int drm_mode_vrefresh(const struct drm_display_mode *mode)
+int drm_mode_vrefresh(struct drm_display_mode *mode)
 {
        int refresh = 0;
        unsigned int calc_val;
@@ -725,7 +725,7 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  * a pointer to it.  Used to create new instances of established modes.
  */
 struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
-                                           const struct drm_display_mode *mode)
+                                           struct drm_display_mode *mode)
 {
        struct drm_display_mode *nmode;
        int new_id;
@@ -974,192 +974,3 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
        }
 }
 EXPORT_SYMBOL(drm_mode_connector_list_update);
-
-/**
- * drm_mode_parse_command_line_for_connector - parse command line for connector
- * @mode_option - per connector mode option
- * @connector - connector to parse line for
- *
- * This parses the connector specific then generic command lines for
- * modes and options to configure the connector.
- *
- * This uses the same parameters as the fb modedb.c, except for extra
- *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
- *
- * enable/enable Digital/disable bit at the end
- */
-bool drm_mode_parse_command_line_for_connector(const char *mode_option,
-                                              struct drm_connector *connector,
-                                              struct drm_cmdline_mode *mode)
-{
-       const char *name;
-       unsigned int namelen;
-       bool res_specified = false, bpp_specified = false, refresh_specified = false;
-       unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
-       bool yres_specified = false, cvt = false, rb = false;
-       bool interlace = false, margins = false, was_digit = false;
-       int i;
-       enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
-
-#ifdef CONFIG_FB
-       if (!mode_option)
-               mode_option = fb_mode_option;
-#endif
-
-       if (!mode_option) {
-               mode->specified = false;
-               return false;
-       }
-
-       name = mode_option;
-       namelen = strlen(name);
-       for (i = namelen-1; i >= 0; i--) {
-               switch (name[i]) {
-               case '@':
-                       if (!refresh_specified && !bpp_specified &&
-                           !yres_specified && !cvt && !rb && was_digit) {
-                               refresh = simple_strtol(&name[i+1], NULL, 10);
-                               refresh_specified = true;
-                               was_digit = false;
-                       } else
-                               goto done;
-                       break;
-               case '-':
-                       if (!bpp_specified && !yres_specified && !cvt &&
-                           !rb && was_digit) {
-                               bpp = simple_strtol(&name[i+1], NULL, 10);
-                               bpp_specified = true;
-                               was_digit = false;
-                       } else
-                               goto done;
-                       break;
-               case 'x':
-                       if (!yres_specified && was_digit) {
-                               yres = simple_strtol(&name[i+1], NULL, 10);
-                               yres_specified = true;
-                               was_digit = false;
-                       } else
-                               goto done;
-               case '0' ... '9':
-                       was_digit = true;
-                       break;
-               case 'M':
-                       if (yres_specified || cvt || was_digit)
-                               goto done;
-                       cvt = true;
-                       break;
-               case 'R':
-                       if (yres_specified || cvt || rb || was_digit)
-                               goto done;
-                       rb = true;
-                       break;
-               case 'm':
-                       if (cvt || yres_specified || was_digit)
-                               goto done;
-                       margins = true;
-                       break;
-               case 'i':
-                       if (cvt || yres_specified || was_digit)
-                               goto done;
-                       interlace = true;
-                       break;
-               case 'e':
-                       if (yres_specified || bpp_specified || refresh_specified ||
-                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
-                               goto done;
-
-                       force = DRM_FORCE_ON;
-                       break;
-               case 'D':
-                       if (yres_specified || bpp_specified || refresh_specified ||
-                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
-                               goto done;
-
-                       if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
-                           (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
-                               force = DRM_FORCE_ON;
-                       else
-                               force = DRM_FORCE_ON_DIGITAL;
-                       break;
-               case 'd':
-                       if (yres_specified || bpp_specified || refresh_specified ||
-                           was_digit || (force != DRM_FORCE_UNSPECIFIED))
-                               goto done;
-
-                       force = DRM_FORCE_OFF;
-                       break;
-               default:
-                       goto done;
-               }
-       }
-
-       if (i < 0 && yres_specified) {
-               char *ch;
-               xres = simple_strtol(name, &ch, 10);
-               if ((ch != NULL) && (*ch == 'x'))
-                       res_specified = true;
-               else
-                       i = ch - name;
-       } else if (!yres_specified && was_digit) {
-               /* catch mode that begins with digits but has no 'x' */
-               i = 0;
-       }
-done:
-       if (i >= 0) {
-               printk(KERN_WARNING
-                       "parse error at position %i in video mode '%s'\n",
-                       i, name);
-               mode->specified = false;
-               return false;
-       }
-
-       if (res_specified) {
-               mode->specified = true;
-               mode->xres = xres;
-               mode->yres = yres;
-       }
-
-       if (refresh_specified) {
-               mode->refresh_specified = true;
-               mode->refresh = refresh;
-       }
-
-       if (bpp_specified) {
-               mode->bpp_specified = true;
-               mode->bpp = bpp;
-       }
-       mode->rb = rb;
-       mode->cvt = cvt;
-       mode->interlace = interlace;
-       mode->margins = margins;
-       mode->force = force;
-
-       return true;
-}
-EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
-
-struct drm_display_mode *
-drm_mode_create_from_cmdline_mode(struct drm_device *dev,
-                                 struct drm_cmdline_mode *cmd)
-{
-       struct drm_display_mode *mode;
-
-       if (cmd->cvt)
-               mode = drm_cvt_mode(dev,
-                                   cmd->xres, cmd->yres,
-                                   cmd->refresh_specified ? cmd->refresh : 60,
-                                   cmd->rb, cmd->interlace,
-                                   cmd->margins);
-       else
-               mode = drm_gtf_mode(dev,
-                                   cmd->xres, cmd->yres,
-                                   cmd->refresh_specified ? cmd->refresh : 60,
-                                   cmd->interlace,
-                                   cmd->margins);
-       if (!mode)
-               return NULL;
-
-       drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-       return mode;
-}
-EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
index b6a19cb..f5bd9e5 100644 (file)
@@ -125,177 +125,6 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 EXPORT_SYMBOL(drm_pci_free);
 
 #ifdef CONFIG_PCI
-
-static int drm_get_pci_domain(struct drm_device *dev)
-{
-#ifndef __alpha__
-       /* For historical reasons, drm_get_pci_domain() is busticated
-        * on most archs and has to remain so for userspace interface
-        * < 1.4, except on alpha which was right from the beginning
-        */
-       if (dev->if_version < 0x10004)
-               return 0;
-#endif /* __alpha__ */
-
-       return pci_domain_nr(dev->pdev->bus);
-}
-
-static int drm_pci_get_irq(struct drm_device *dev)
-{
-       return dev->pdev->irq;
-}
-
-static const char *drm_pci_get_name(struct drm_device *dev)
-{
-       struct pci_driver *pdriver = dev->driver->kdriver.pci;
-       return pdriver->name;
-}
-
-int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
-{
-       int len, ret;
-       struct pci_driver *pdriver = dev->driver->kdriver.pci;
-       master->unique_len = 40;
-       master->unique_size = master->unique_len;
-       master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-       if (master->unique == NULL)
-               return -ENOMEM;
-
-
-       len = snprintf(master->unique, master->unique_len,
-                      "pci:%04x:%02x:%02x.%d",
-                      drm_get_pci_domain(dev),
-                      dev->pdev->bus->number,
-                      PCI_SLOT(dev->pdev->devfn),
-                      PCI_FUNC(dev->pdev->devfn));
-
-       if (len >= master->unique_len) {
-               DRM_ERROR("buffer overflow");
-               ret = -EINVAL;
-               goto err;
-       } else
-               master->unique_len = len;
-
-       dev->devname =
-               kmalloc(strlen(pdriver->name) +
-                       master->unique_len + 2, GFP_KERNEL);
-
-       if (dev->devname == NULL) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       sprintf(dev->devname, "%s@%s", pdriver->name,
-               master->unique);
-
-       return 0;
-err:
-       return ret;
-}
-
-int drm_pci_set_unique(struct drm_device *dev,
-                      struct drm_master *master,
-                      struct drm_unique *u)
-{
-       int domain, bus, slot, func, ret;
-       const char *bus_name;
-
-       master->unique_len = u->unique_len;
-       master->unique_size = u->unique_len + 1;
-       master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-       if (!master->unique) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       if (copy_from_user(master->unique, u->unique, master->unique_len)) {
-               ret = -EFAULT;
-               goto err;
-       }
-
-       master->unique[master->unique_len] = '\0';
-
-       bus_name = dev->driver->bus->get_name(dev);
-       dev->devname = kmalloc(strlen(bus_name) +
-                              strlen(master->unique) + 2, GFP_KERNEL);
-       if (!dev->devname) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       sprintf(dev->devname, "%s@%s", bus_name,
-               master->unique);
-
-       /* Return error if the busid submitted doesn't match the device's actual
-        * busid.
-        */
-       ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
-       if (ret != 3) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       domain = bus >> 8;
-       bus &= 0xff;
-
-       if ((domain != drm_get_pci_domain(dev)) ||
-           (bus != dev->pdev->bus->number) ||
-           (slot != PCI_SLOT(dev->pdev->devfn)) ||
-           (func != PCI_FUNC(dev->pdev->devfn))) {
-               ret = -EINVAL;
-               goto err;
-       }
-       return 0;
-err:
-       return ret;
-}
-
-
-static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
-{
-       if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
-           (p->busnum & 0xff) != dev->pdev->bus->number ||
-           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-               return -EINVAL;
-
-       p->irq = dev->pdev->irq;
-
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-                 p->irq);
-       return 0;
-}
-
-int drm_pci_agp_init(struct drm_device *dev)
-{
-       if (drm_core_has_AGP(dev)) {
-               if (drm_pci_device_is_agp(dev))
-                       dev->agp = drm_agp_init(dev);
-               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-                   && (dev->agp == NULL)) {
-                       DRM_ERROR("Cannot initialize the agpgart module.\n");
-                       return -EINVAL;
-               }
-               if (drm_core_has_MTRR(dev)) {
-                       if (dev->agp)
-                               dev->agp->agp_mtrr =
-                                       mtrr_add(dev->agp->agp_info.aper_base,
-                                                dev->agp->agp_info.aper_size *
-                                                1024 * 1024, MTRR_TYPE_WRCOMB, 1);
-               }
-       }
-       return 0;
-}
-
-static struct drm_bus drm_pci_bus = {
-       .bus_type = DRIVER_BUS_PCI,
-       .get_irq = drm_pci_get_irq,
-       .get_name = drm_pci_get_name,
-       .set_busid = drm_pci_set_busid,
-       .set_unique = drm_pci_set_unique,
-       .irq_by_busid = drm_pci_irq_by_busid,
-       .agp_init = drm_pci_agp_init,
-};
-
 /**
  * Register.
  *
@@ -390,7 +219,7 @@ err_g1:
 EXPORT_SYMBOL(drm_get_pci_dev);
 
 /**
- * PCI device initialization. Called direct from modules at load time.
+ * PCI device initialization. Called via drm_init at module load time,
  *
  * \return zero on success or a negative number on failure.
  *
@@ -400,24 +229,18 @@ EXPORT_SYMBOL(drm_get_pci_dev);
  * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
  * after the initialization for driver customization.
  */
-int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
+int drm_pci_init(struct drm_driver *driver)
 {
        struct pci_dev *pdev = NULL;
        const struct pci_device_id *pid;
        int i;
 
-       DRM_DEBUG("\n");
-
-       INIT_LIST_HEAD(&driver->device_list);
-       driver->kdriver.pci = pdriver;
-       driver->bus = &drm_pci_bus;
-
        if (driver->driver_features & DRIVER_MODESET)
-               return pci_register_driver(pdriver);
+               return pci_register_driver(&driver->pci_driver);
 
        /* If not using KMS, fall back to stealth mode manual scanning. */
-       for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
-               pid = &pdriver->id_table[i];
+       for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
+               pid = &driver->pci_driver.id_table[i];
 
                /* Loop around setting up a DRM device for each PCI device
                 * matching our ID and device class.  If we had the internal
@@ -442,27 +265,10 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 
 #else
 
-int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
+int drm_pci_init(struct drm_driver *driver)
 {
        return -1;
 }
 
 #endif
-
-EXPORT_SYMBOL(drm_pci_init);
-
 /*@}*/
-void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
-{
-       struct drm_device *dev, *tmp;
-       DRM_DEBUG("\n");
-
-       if (driver->driver_features & DRIVER_MODESET) {
-               pci_unregister_driver(pdriver);
-       } else {
-               list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-                       drm_put_dev(dev);
-       }
-       DRM_INFO("Module unloaded\n");
-}
-EXPORT_SYMBOL(drm_pci_exit);
index 2a8b626..92d1d0f 100644 (file)
@@ -109,61 +109,8 @@ err_g1:
 }
 EXPORT_SYMBOL(drm_get_platform_dev);
 
-static int drm_platform_get_irq(struct drm_device *dev)
-{
-       return platform_get_irq(dev->platformdev, 0);
-}
-
-static const char *drm_platform_get_name(struct drm_device *dev)
-{
-       return dev->platformdev->name;
-}
-
-static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master)
-{
-       int len, ret;
-
-       master->unique_len = 13 + strlen(dev->platformdev->name);
-       master->unique_size = master->unique_len;
-       master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-
-       if (master->unique == NULL)
-               return -ENOMEM;
-
-       len = snprintf(master->unique, master->unique_len,
-                       "platform:%s:%02d", dev->platformdev->name, dev->platformdev->id);
-
-       if (len > master->unique_len) {
-               DRM_ERROR("Unique buffer overflowed\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       dev->devname =
-               kmalloc(strlen(dev->platformdev->name) +
-                       master->unique_len + 2, GFP_KERNEL);
-
-       if (dev->devname == NULL) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       sprintf(dev->devname, "%s@%s", dev->platformdev->name,
-               master->unique);
-       return 0;
-err:
-       return ret;
-}
-
-static struct drm_bus drm_platform_bus = {
-       .bus_type = DRIVER_BUS_PLATFORM,
-       .get_irq = drm_platform_get_irq,
-       .get_name = drm_platform_get_name,
-       .set_busid = drm_platform_set_busid,
-};
-
 /**
- * Platform device initialization. Called direct from modules.
+ * Platform device initialization. Called via drm_init at module load time,
  *
  * \return zero on success or a negative number on failure.
  *
@@ -174,24 +121,7 @@ static struct drm_bus drm_platform_bus = {
  * after the initialization for driver customization.
  */
 
-int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device)
+int drm_platform_init(struct drm_driver *driver)
 {
-       DRM_DEBUG("\n");
-
-       driver->kdriver.platform_device = platform_device;
-       driver->bus = &drm_platform_bus;
-       INIT_LIST_HEAD(&driver->device_list);
-       return drm_get_platform_dev(platform_device, driver);
-}
-EXPORT_SYMBOL(drm_platform_init);
-
-void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device)
-{
-       struct drm_device *dev, *tmp;
-       DRM_DEBUG("\n");
-
-       list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-               drm_put_dev(dev);
-       DRM_INFO("Module unloaded\n");
+       return drm_get_platform_dev(driver->platform_device, driver);
 }
-EXPORT_SYMBOL(drm_platform_exit);
index 7525e03..d15e09b 100644 (file)
@@ -83,26 +83,30 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
        if (dev->sg)
                return -EINVAL;
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
+       memset(entry, 0, sizeof(*entry));
        pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
        DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
 
        entry->pages = pages;
-       entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL);
+       entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
        if (!entry->pagelist) {
                kfree(entry);
                return -ENOMEM;
        }
 
-       entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL);
+       memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
+
+       entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
        if (!entry->busaddr) {
                kfree(entry->pagelist);
                kfree(entry);
                return -ENOMEM;
        }
+       memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
 
        entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
        if (!entry->virtual) {
index 3466458..463aed9 100644 (file)
@@ -59,7 +59,9 @@ drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 {
        int ret = 0;
 
-       sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL);
+       sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
+                                                 sizeof(*sman->mm),
+                                                 GFP_KERNEL);
        if (!sman->mm) {
                ret = -ENOMEM;
                goto out;
index 6d7b083..cdc89ee 100644 (file)
 unsigned int drm_debug = 0;    /* 1 to enable debug output */
 EXPORT_SYMBOL(drm_debug);
 
-unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
-EXPORT_SYMBOL(drm_vblank_offdelay);
-
-unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
-EXPORT_SYMBOL(drm_timestamp_precision);
-
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output");
-MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
-MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
 
 module_param_named(debug, drm_debug, int, 0600);
-module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
-module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
 
 struct idr drm_minors_idr;
 
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 struct dentry *drm_debugfs_root;
-
-int drm_err(const char *func, const char *format, ...)
-{
-       struct va_format vaf;
-       va_list args;
-       int r;
-
-       va_start(args, format);
-
-       vaf.fmt = format;
-       vaf.va = &args;
-
-       r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
-
-       va_end(args);
-
-       return r;
-}
-EXPORT_SYMBOL(drm_err);
-
 void drm_ut_debug_printk(unsigned int request_level,
                         const char *prefix,
                         const char *function_name,
@@ -98,7 +68,6 @@ void drm_ut_debug_printk(unsigned int request_level,
        }
 }
 EXPORT_SYMBOL(drm_ut_debug_printk);
-
 static int drm_minor_get_id(struct drm_device *dev, int type)
 {
        int new_id;
@@ -290,14 +259,25 @@ int drm_fill_in_dev(struct drm_device *dev,
 
        dev->driver = driver;
 
-       if (dev->driver->bus->agp_init) {
-               retcode = dev->driver->bus->agp_init(dev);
-               if (retcode)
+       if (drm_core_has_AGP(dev)) {
+               if (drm_device_is_agp(dev))
+                       dev->agp = drm_agp_init(dev);
+               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+                   && (dev->agp == NULL)) {
+                       DRM_ERROR("Cannot initialize the agpgart module.\n");
+                       retcode = -EINVAL;
                        goto error_out_unreg;
+               }
+               if (drm_core_has_MTRR(dev)) {
+                       if (dev->agp)
+                               dev->agp->agp_mtrr =
+                                   mtrr_add(dev->agp->agp_info.aper_base,
+                                            dev->agp->agp_info.aper_size *
+                                            1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+               }
        }
 
 
-
        retcode = drm_ctxbitmap_init(dev);
        if (retcode) {
                DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -435,6 +415,7 @@ int drm_put_minor(struct drm_minor **minor_p)
  *
  * Cleans up all DRM device, calling drm_lastclose().
  *
+ * \sa drm_init
  */
 void drm_put_dev(struct drm_device *dev)
 {
@@ -484,7 +465,6 @@ void drm_put_dev(struct drm_device *dev)
 
        drm_put_minor(&dev->primary);
 
-       list_del(&dev->driver_item);
        if (dev->devname) {
                kfree(dev->devname);
                dev->devname = NULL;
index 2eee8e0..85da4c4 100644 (file)
@@ -158,15 +158,8 @@ static ssize_t status_show(struct device *device,
 {
        struct drm_connector *connector = to_drm_connector(device);
        enum drm_connector_status status;
-       int ret;
-
-       ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex);
-       if (ret)
-               return ret;
 
        status = connector->funcs->detect(connector, true);
-       mutex_unlock(&connector->dev->mode_config.mutex);
-
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        drm_get_connector_status_name(status));
 }
index 5db96d4..2c3fcbd 100644 (file)
@@ -526,7 +526,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
 {
 #ifdef __alpha__
-       return dev->hose->dense_mem_base;
+       return dev->hose->dense_mem_base - dev->hose->mem_space->start;
 #else
        return 0;
 #endif
index 54462a5..052618d 100644 (file)
@@ -409,7 +409,7 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO       *psDevInfo,
         }
 
 #else
-        if(!cpu_is_omap3530())
+        if(!(cpu_is_omap3530() || cpu_is_omap3517()))
        {
                OSWriteHWReg(psDevInfo->pvRegsBaseKM, 0xFF08, 0x80000000);//OCP Bypass mode
        }
index f7fa57b..ad39b05 100644 (file)
 #else
 #define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
 #endif
-/*
+
 #if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
-#error "A preemptible Linux kernel is required when using workqueues"
+//#error "A preemptible Linux kernel is required when using workqueues"
 #endif
-*/
+
 #define EVENT_OBJECT_TIMEOUT_MS                (100)
 
 #define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
@@ -139,14 +139,12 @@ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOI
 
 static inline int is_vmalloc_addr(const void *pvCpuVAddr)
 {
-        unsigned long lAddr = (unsigned long)pvCpuVAddr;
-        return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
+       unsigned long lAddr = (unsigned long)pvCpuVAddr;
+       return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
 }
 
-#endif
-
+#endif 
 
-       
 #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
 PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
 #else
@@ -526,12 +524,12 @@ IMG_UINT32 OSClockus(IMG_VOID)
 }
 
 
 IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
 {
     udelay(ui32Timeus);
 }
 
+
 IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
 {
     msleep(ui32Timems);
@@ -2602,10 +2600,6 @@ error:
 }
 
 typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-typedef void (*InnerCacheOp_mapUnmap_t)(const void *pvStart, const IMG_UINT32 size, const IMG_UINT32 type);
-#endif
-
 typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
 
 #if defined(CONFIG_OUTER_CACHE)
@@ -2671,34 +2665,19 @@ IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
 
        return IMG_NULL;
 }
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+
 static
 IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
                                                         IMG_VOID *pvRangeAddrStart,
                                                         IMG_UINT32 ui32Length,
-                                                        void * pfnInnerCacheOp_ptr,
-                                                        OuterCacheOp_t pfnOuterCacheOp,
-                                                         IMG_UINT32 map_unmap)
-#else
-static
-IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
-                                                         IMG_VOID *pvRangeAddrStart,
-                                                         IMG_UINT32 ui32Length,
-                                                         InnerCacheOp_t pfnInnerCacheOp,
-                                                         OuterCacheOp_t pfnOuterCacheOp)
-#endif
-
+                                                        InnerCacheOp_t pfnInnerCacheOp,
+                                                        OuterCacheOp_t pfnOuterCacheOp)
 {
        LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
        IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0;
        struct list_head *psMMapOffsetStructList;
        IMG_VOID *pvMinVAddr;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))        
-        InnerCacheOp_t pfnInnerCacheOp = (InnerCacheOp_t)pfnInnerCacheOp_ptr;
-        InnerCacheOp_mapUnmap_t pfnInnerCacheOp_mapUnamp = (InnerCacheOp_mapUnmap_t)pfnInnerCacheOp_ptr;
-#endif
-
 #if defined(CONFIG_OUTER_CACHE)
        MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
        IMG_UINT32 ui32PageNumOffset = 0;
@@ -2724,70 +2703,38 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
        {
                case LINUX_MEM_AREA_VMALLOC:
                {
-                if(is_vmalloc_addr(pvRangeAddrStart))
-                        {
-       
-                              pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
-
-                                if(pvRangeAddrStart < pvMinVAddr)
-                                        goto err_blocked;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-        if (map_unmap == 0 ) {
-
-           pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-
-        } else if (map_unmap == 1) {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_TO_DEVICE);
-
-        } else {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_FROM_DEVICE);
-
-        }
-#else
-pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-#endif
-
-//                                pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-                        }
-
-               else
-                {
-
-                                pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,pvRangeAddrStart, ui32Length);
-                                if(!pvMinVAddr)
-                                        goto err_blocked;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-        if (map_unmap == 0 ) {
-
-           pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-
-        } else if (map_unmap == 1) {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_TO_DEVICE);
-
-        } else {
+                       if(is_vmalloc_addr(pvRangeAddrStart))
+                       {
+                               pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
 
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_FROM_DEVICE);
+                               
+                               if(pvRangeAddrStart < pvMinVAddr)
+                                       goto err_blocked;
 
-        }
-#else
-pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-#endif
+                               pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+                       }
+                       else
+                       {
+                               
+                               
 
+                               pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+                                                                                          pvRangeAddrStart, ui32Length);
+                               if(!pvMinVAddr)
+                                       goto err_blocked;
 
-//                                pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-                       
+                               pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
 
 #if defined(CONFIG_OUTER_CACHE)
-                               pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +(ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
-                  }
+                               
+                               pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+                                                                  (ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
+                       }
 
                        pfnMemAreaToPhys = VMallocAreaToPhys;
-#else
-}
-#endif
+#else 
+                       }
+#endif 
                        break;
                }
 
@@ -2815,26 +2762,8 @@ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
                                                                                   pvRangeAddrStart, ui32Length);
                        if(!pvMinVAddr)
                                goto err_blocked;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-        if (map_unmap == 0 ) {
-
-           pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-
-        } else if (map_unmap == 1) {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_TO_DEVICE);
-
-        } else {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_FROM_DEVICE);
-
-        }
-#else
-pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-#endif
-
-//                     pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
 
+                       pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
 
 #if defined(CONFIG_OUTER_CACHE)
                        ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
@@ -2849,25 +2778,8 @@ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
                                                                                   pvRangeAddrStart, ui32Length);
                        if(!pvMinVAddr)
                                goto err_blocked;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-        if (map_unmap == 0 ) {
-
-           pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-
-        } else if (map_unmap == 1) {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_TO_DEVICE);
 
-        } else {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_FROM_DEVICE);
-
-        }
-#else
-pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-#endif
-
-               //      pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+                       pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
 
 #if defined(CONFIG_OUTER_CACHE)
                        ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
@@ -2880,31 +2792,10 @@ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
                        PVR_DBG_BREAK;
        }
 
-#if 0
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-        if (map_unmap == 0 ) {
-
-           pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-
-        } else if (map_unmap == 1) {
-       
-          pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_TO_DEVICE);
-
-        } else {
-
-           pfnInnerCacheOp_mapUnamp (pvRangeAddrStart, ui32Length, DMA_FROM_DEVICE);
-
-        }
-#else
-pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
-#endif
-#endif
-
 #if defined(CONFIG_OUTER_CACHE)
-       
-//     if (pfnMemAreaToPhys != IMG_NULL)
-      PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
+       PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
 
+       
        {
                unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
                IMG_UINT32 i, ui32NumPages;
@@ -2932,10 +2823,6 @@ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
                        pfnOuterCacheOp(ulStart, ulEnd);
                }
        }
-//     else
-//     {
-//             PVR_DBG_BREAK;
-//     }
 #endif
 
        return IMG_TRUE;
@@ -2947,7 +2834,8 @@ err_blocked:
                         psLinuxMemArea->eAreaType));
        return IMG_FALSE;
 }
-#endif 
+
+#endif
 
 #if defined(__i386__)
 
@@ -2989,40 +2877,27 @@ IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
                                                                IMG_VOID *pvRangeAddrStart,
                                                                IMG_UINT32 ui32Length)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))     
+       
        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                          (void *) x86_flush_cache_range, IMG_NULL, 0);
-#else
-       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           x86_flush_cache_range, IMG_NULL);
-
-#endif
+                                                          x86_flush_cache_range, IMG_NULL);
 }
 
 IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
                                                                IMG_VOID *pvRangeAddrStart,
                                                                IMG_UINT32 ui32Length)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))     
+       
        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                          (void *) x86_flush_cache_range, IMG_NULL, 0);
-#else
-       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           x86_flush_cache_range, IMG_NULL);
-#endif
+                                                          x86_flush_cache_range, IMG_NULL);
 }
 
 IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
                                                                         IMG_VOID *pvRangeAddrStart,
                                                                         IMG_UINT32 ui32Length)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))     
+       
        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                          (void *) x86_flush_cache_range, IMG_NULL, 0);
-#else
-        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           x86_flush_cache_range, IMG_NULL);
-#endif
+                                                          x86_flush_cache_range, IMG_NULL);
 }
 
 #else 
@@ -3051,52 +2926,55 @@ IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
        outer_flush_all();
 #endif
 }
+static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
+{
+        return (size_t)((char *)pvEnd - (char *)pvStart);
+}
 
-IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
-                                                               IMG_VOID *pvRangeAddrStart,
-                                                               IMG_UINT32 ui32Length)
+
+static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                          (void *) dmac_flush_range, outer_flush_range, 0);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+        dmac_inv_range(pvStart, pvEnd);
 #else
-        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           dmac_flush_range, outer_flush_range);
+        dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_FROM_DEVICE);
 #endif
+}
 
+static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+        dmac_clean_range(pvStart, pvEnd);
+#else
+        dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_TO_DEVICE);
+#endif
 }
 
-IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
                                                                IMG_VOID *pvRangeAddrStart,
                                                                IMG_UINT32 ui32Length)
-{ 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           (void *) dmac_map_area, outer_clean_range, 2);
-#else
-        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           dmac_clean_range, outer_clean_range);
-#endif
+{
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,dmac_flush_range, (OuterCacheOp_t)outer_flush_range);
+}
 
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+                                                               IMG_VOID *pvRangeAddrStart,
+                                                               IMG_UINT32 ui32Length)
+{
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,pvr_dmac_clean_range, (OuterCacheOp_t)outer_clean_range);
 }
 
 IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
                                                                         IMG_VOID *pvRangeAddrStart,
                                                                         IMG_UINT32 ui32Length)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
-       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                          (void *) dmac_unmap_area, outer_inv_range, 1);
-#else
-        return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
-                                                           dmac_inv_range, outer_inv_range);
-#endif
+       return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,pvr_dmac_inv_range, (OuterCacheOp_t)outer_inv_range);
 }
 
 #else 
 
 #if defined(__mips__)
-
 IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
 {
        
@@ -3133,8 +3011,7 @@ IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
        return IMG_TRUE;
 }
 
-
-#else
+#else 
 
 #error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"