From: Imagination Technologies/TI Date: Mon, 11 Feb 2013 00:38:15 +0000 (+0200) Subject: 1.6.16.4117/4.05.00.03 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=36fccf9d7e9b579453219234cc852d3586fd7c26;p=sgx.git 1.6.16.4117/4.05.00.03 --- diff --git a/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c b/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c index 8aac78a..248e964 100644 --- a/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c +++ b/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c @@ -24,11 +24,14 @@ * ******************************************************************************/ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) #ifndef AUTOCONF_INCLUDED #include #endif +#endif -#include #include @@ -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 diff --git a/services4/3rdparty/dc_ti81xx_linux/omaplfb_displayclass.c b/services4/3rdparty/dc_ti81xx_linux/omaplfb_displayclass.c index b5ba0d1..b1bb8df 100644 --- a/services4/3rdparty/dc_ti81xx_linux/omaplfb_displayclass.c +++ b/services4/3rdparty/dc_ti81xx_linux/omaplfb_displayclass.c @@ -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) diff --git a/services4/3rdparty/dc_ti81xx_linux/omaplfb_linux.c b/services4/3rdparty/dc_ti81xx_linux/omaplfb_linux.c index 619624c..74134c6 100644 --- a/services4/3rdparty/dc_ti81xx_linux/omaplfb_linux.c +++ b/services4/3rdparty/dc_ti81xx_linux/omaplfb_linux.c @@ -24,11 +24,14 @@ * ******************************************************************************/ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) #ifndef AUTOCONF_INCLUDED #include #endif +#endif -#include #include @@ -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; diff --git a/services4/3rdparty/linux_drm/drm_agpsupport.c b/services4/3rdparty/linux_drm/drm_agpsupport.c index 0cb2ba5..252fdb9 100644 --- a/services4/3rdparty/linux_drm/drm_agpsupport.c +++ b/services4/3rdparty/linux_drm/drm_agpsupport.c @@ -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 */ diff --git a/services4/3rdparty/linux_drm/drm_bufs.c b/services4/3rdparty/linux_drm/drm_bufs.c index 61e1ef9..3e257a5 100644 --- a/services4/3rdparty/linux_drm/drm_bufs.c +++ b/services4/3rdparty/linux_drm/drm_bufs.c @@ -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 diff --git a/services4/3rdparty/linux_drm/drm_crtc.c b/services4/3rdparty/linux_drm/drm_crtc.c index fe738f0..2baa670 100644 --- a/services4/3rdparty/linux_drm/drm_crtc.c +++ b/services4/3rdparty/linux_drm/drm_crtc.c @@ -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); -} diff --git a/services4/3rdparty/linux_drm/drm_crtc_helper.c b/services4/3rdparty/linux_drm/drm_crtc_helper.c index f88a9b2..2d4e17a 100644 --- a/services4/3rdparty/linux_drm/drm_crtc_helper.c +++ b/services4/3rdparty/linux_drm/drm_crtc_helper.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_debugfs.c b/services4/3rdparty/linux_drm/drm_debugfs.c index 9d2668a..9d8c892 100644 --- a/services4/3rdparty/linux_drm/drm_debugfs.c +++ b/services4/3rdparty/linux_drm/drm_debugfs.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_drv.c b/services4/3rdparty/linux_drm/drm_drv.c index 93a112d..271835a 100644 --- a/services4/3rdparty/linux_drm/drm_drv.c +++ b/services4/3rdparty/linux_drm/drm_drv.c @@ -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, diff --git a/services4/3rdparty/linux_drm/drm_edid.c b/services4/3rdparty/linux_drm/drm_edid.c index 7425e5c..a245d17 100644 --- a/services4/3rdparty/linux_drm/drm_edid.c +++ b/services4/3rdparty/linux_drm/drm_edid.c @@ -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 diff --git a/services4/3rdparty/linux_drm/drm_fb_helper.c b/services4/3rdparty/linux_drm/drm_fb_helper.c index f7c6854..d2849e4 100644 --- a/services4/3rdparty/linux_drm/drm_fb_helper.c +++ b/services4/3rdparty/linux_drm/drm_fb_helper.c @@ -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 + * x[M][R][-][@][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 diff --git a/services4/3rdparty/linux_drm/drm_fops.c b/services4/3rdparty/linux_drm/drm_fops.c index 2ec7d48..a39794b 100644 --- a/services4/3rdparty/linux_drm/drm_fops.c +++ b/services4/3rdparty/linux_drm/drm_fops.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_gem.c b/services4/3rdparty/linux_drm/drm_gem.c index 186d62e..ea1c4b0 100644 --- a/services4/3rdparty/linux_drm/drm_gem.c +++ b/services4/3rdparty/linux_drm/drm_gem.c @@ -34,7 +34,6 @@ #include #include #include -#include #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); diff --git a/services4/3rdparty/linux_drm/drm_hashtab.c b/services4/3rdparty/linux_drm/drm_hashtab.c index e3a7568..a93d7b4 100644 --- a/services4/3rdparty/linux_drm/drm_hashtab.c +++ b/services4/3rdparty/linux_drm/drm_hashtab.c @@ -39,18 +39,27 @@ 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; } } diff --git a/services4/3rdparty/linux_drm/drm_info.c b/services4/3rdparty/linux_drm/drm_info.c index ab1162d..3cdbaf3 100644 --- a/services4/3rdparty/linux_drm/drm_info.c +++ b/services4/3rdparty/linux_drm/drm_info.c @@ -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' : '-', diff --git a/services4/3rdparty/linux_drm/drm_ioc32.c b/services4/3rdparty/linux_drm/drm_ioc32.c index 4a058c7..d61d185 100644 --- a/services4/3rdparty/linux_drm/drm_ioc32.c +++ b/services4/3rdparty/linux_drm/drm_ioc32.c @@ -28,7 +28,6 @@ * IN THE SOFTWARE. */ #include -#include #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; diff --git a/services4/3rdparty/linux_drm/drm_ioctl.c b/services4/3rdparty/linux_drm/drm_ioctl.c index 904d7e9..47db4df 100644 --- a/services4/3rdparty/linux_drm/drm_ioctl.c +++ b/services4/3rdparty/linux_drm/drm_ioctl.c @@ -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. * diff --git a/services4/3rdparty/linux_drm/drm_irq.c b/services4/3rdparty/linux_drm/drm_irq.c index 3830e9e..16d5155 100644 --- a/services4/3rdparty/linux_drm/drm_irq.c +++ b/services4/3rdparty/linux_drm/drm_irq.c @@ -40,22 +40,6 @@ #include #include - -/* 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); diff --git a/services4/3rdparty/linux_drm/drm_mm.c b/services4/3rdparty/linux_drm/drm_mm.c index 959186c..a6bfc30 100644 --- a/services4/3rdparty/linux_drm/drm_mm.c +++ b/services4/3rdparty/linux_drm/drm_mm.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_modes.c b/services4/3rdparty/linux_drm/drm_modes.c index ad74fb4..58e65f9 100644 --- a/services4/3rdparty/linux_drm/drm_modes.c +++ b/services4/3rdparty/linux_drm/drm_modes.c @@ -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 - * x[M][R][-][@][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); diff --git a/services4/3rdparty/linux_drm/drm_pci.c b/services4/3rdparty/linux_drm/drm_pci.c index b6a19cb..f5bd9e5 100644 --- a/services4/3rdparty/linux_drm/drm_pci.c +++ b/services4/3rdparty/linux_drm/drm_pci.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_platform.c b/services4/3rdparty/linux_drm/drm_platform.c index 2a8b626..92d1d0f 100644 --- a/services4/3rdparty/linux_drm/drm_platform.c +++ b/services4/3rdparty/linux_drm/drm_platform.c @@ -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); diff --git a/services4/3rdparty/linux_drm/drm_scatter.c b/services4/3rdparty/linux_drm/drm_scatter.c index 7525e03..d15e09b 100644 --- a/services4/3rdparty/linux_drm/drm_scatter.c +++ b/services4/3rdparty/linux_drm/drm_scatter.c @@ -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) { diff --git a/services4/3rdparty/linux_drm/drm_sman.c b/services4/3rdparty/linux_drm/drm_sman.c index 3466458..463aed9 100644 --- a/services4/3rdparty/linux_drm/drm_sman.c +++ b/services4/3rdparty/linux_drm/drm_sman.c @@ -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; diff --git a/services4/3rdparty/linux_drm/drm_stub.c b/services4/3rdparty/linux_drm/drm_stub.c index 6d7b083..cdc89ee 100644 --- a/services4/3rdparty/linux_drm/drm_stub.c +++ b/services4/3rdparty/linux_drm/drm_stub.c @@ -40,48 +40,18 @@ 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; diff --git a/services4/3rdparty/linux_drm/drm_sysfs.c b/services4/3rdparty/linux_drm/drm_sysfs.c index 2eee8e0..85da4c4 100644 --- a/services4/3rdparty/linux_drm/drm_sysfs.c +++ b/services4/3rdparty/linux_drm/drm_sysfs.c @@ -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)); } diff --git a/services4/3rdparty/linux_drm/drm_vm.c b/services4/3rdparty/linux_drm/drm_vm.c index 5db96d4..2c3fcbd 100644 --- a/services4/3rdparty/linux_drm/drm_vm.c +++ b/services4/3rdparty/linux_drm/drm_vm.c @@ -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 diff --git a/services4/srvkm/devices/sgx/sgxinit.c b/services4/srvkm/devices/sgx/sgxinit.c index 54462a5..052618d 100644 --- a/services4/srvkm/devices/sgx/sgxinit.c +++ b/services4/srvkm/devices/sgx/sgxinit.c @@ -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 } diff --git a/services4/srvkm/env/linux/osfunc.c b/services4/srvkm/env/linux/osfunc.c index f7fa57b..ad39b05 100644 --- a/services4/srvkm/env/linux/osfunc.c +++ b/services4/srvkm/env/linux/osfunc.c @@ -79,11 +79,11 @@ #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!"