GIT 2975010b788268760c0a32c45dff20f566ab9d1e master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git#drm-initmap --- Index: drivers/char/drm/drmP.h =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drmP.h (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drmP.h (mode:100644) @@ -91,11 +91,12 @@ #define DRIVER_USE_MTRR 0x4 #define DRIVER_PCI_DMA 0x8 #define DRIVER_SG 0x10 -#define DRIVER_HAVE_DMA 0x20 -#define DRIVER_HAVE_IRQ 0x40 -#define DRIVER_IRQ_SHARED 0x80 -#define DRIVER_IRQ_VBL 0x100 -#define DRIVER_DMA_QUEUE 0x200 +#define DRIVER_FB_DMA 0x20 +#define DRIVER_HAVE_DMA 0x40 +#define DRIVER_HAVE_IRQ 0x80 +#define DRIVER_IRQ_SHARED 0x100 +#define DRIVER_IRQ_VBL 0x200 +#define DRIVER_DMA_QUEUE 0x400 /***********************************************************************/ /** \name Begin the DRM... */ @@ -588,6 +589,7 @@ int (*version)(drm_version_t *version); u32 driver_features; int dev_priv_size; + int permanent_maps; drm_ioctl_desc_t *ioctls; int num_ioctls; struct file_operations fops; @@ -902,6 +904,9 @@ unsigned int cmd, unsigned long arg ); extern int drm_rmmap( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int drm_initmap( drm_device_t *dev, unsigned int offset, + unsigned int size, unsigned int resource, + int type, int flags); extern int drm_addbufs( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int drm_infobufs( struct inode *inode, struct file *filp, @@ -912,6 +917,11 @@ unsigned int cmd, unsigned long arg ); extern int drm_mapbufs( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern unsigned long drm_get_resource_start(drm_device_t *dev, + unsigned int resource); +extern unsigned long drm_get_resource_len(drm_device_t *dev, + unsigned int resource); + /* DMA support (drm_dma.h) */ extern int drm_dma_setup(drm_device_t *dev); Index: drivers/char/drm/drm_bufs.c =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_bufs.c (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_bufs.c (mode:100644) @@ -60,6 +60,79 @@ } EXPORT_SYMBOL(drm_order); +unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource) +{ + return pci_resource_start(dev->pdev, resource); +} +EXPORT_SYMBOL(drm_get_resource_start); + +unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) +{ + return pci_resource_len(dev->pdev, resource); +} +EXPORT_SYMBOL(drm_get_resource_len); + +/** + * Adjusts the memory offset to its absolute value according to the mapping + * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where + * applicable and if supported by the kernel. + */ +int drm_initmap(drm_device_t * dev, unsigned int offset, unsigned int size, + unsigned int resource, int type, int flags) +{ + drm_map_t *map; + drm_map_list_t *list; + + DRM_DEBUG("\n"); + + if ((offset & (~PAGE_MASK)) || (size & (~PAGE_MASK))) + return -EINVAL; +#if !defined(__sparc__) && !defined(__alpha__) + if (offset + size < offset || offset < virt_to_phys(high_memory)) + return -EINVAL; +#endif + if (!(list = drm_alloc(sizeof(*list), DRM_MEM_MAPS))) + return -ENOMEM; + memset(list, 0, sizeof(*list)); + + if (!(map = drm_alloc(sizeof(*map), DRM_MEM_MAPS))) { + drm_free(list, sizeof(*list), DRM_MEM_MAPS); + return -ENOMEM; + } + + *map = (drm_map_t) { + .offset = offset,.size = size,.type = type,.flags = + flags,.mtrr = -1,.handle = 0,}; + list->map = map; + + DRM_DEBUG("initmap offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type); + +#ifdef __alpha__ + map->offset += dev->hose->mem_space->start; +#endif + if (drm_core_has_MTRR(dev)) { + if (map->type == _DRM_FRAME_BUFFER || + (map->flags & _DRM_WRITE_COMBINING)) { + map->mtrr = mtrr_add(map->offset, map->size, + MTRR_TYPE_WRCOMB, 1); + } + } + + if (map->type == _DRM_REGISTERS) + map->handle = drm_ioremap(map->offset, map->size, dev); + + down(&dev->struct_sem); + list_add(&list->head, &dev->maplist->head); + up(&dev->struct_sem); + + dev->driver->permanent_maps = 1; + DRM_DEBUG("finished\n"); + + return 0; +} +EXPORT_SYMBOL(drm_initmap); + /** * Ioctl to specify a range of memory that is available for mapping by a non-root process. * @@ -113,6 +186,39 @@ switch ( map->type ) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: + { + /* after all the drivers switch to permanent mapping this should just return an error */ + struct list_head *_list; + + /* If permanent maps are implemented, maps must match */ + if (dev->driver->permanent_maps) { + DRM_DEBUG("Looking for: offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type); + list_for_each(_list, &dev->maplist->head) { + drm_map_list_t *_entry = + list_entry(_list, drm_map_list_t, + head); + DRM_DEBUG("Checking: offset = 0x%08lx, size = 0x%08lx, type = %d\n", + _entry->map->offset, + _entry->map->size, + _entry->map->type); + if (_entry->map + && map->type == _entry->map->type + && map->offset == + _entry->map->offset) { + _entry->map->size = map->size; + drm_free(map, sizeof(*map), + DRM_MEM_MAPS); + map = _entry->map; + DRM_DEBUG("Found existing: offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, + map->type); + goto found_it; + } + } + /* addmap didn't match an existing permanent map, that's an error */ + return -EINVAL; + } #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) if ( map->offset + map->size < map->offset || map->offset < virt_to_phys(high_memory) ) { @@ -134,7 +240,7 @@ map->handle = drm_ioremap( map->offset, map->size, dev ); break; - + } case _DRM_SHM: map->handle = vmalloc_32(map->size); DRM_DEBUG( "%lu %d %p\n", @@ -188,7 +294,7 @@ down(&dev->struct_sem); list_add(&list->head, &dev->maplist->head); up(&dev->struct_sem); - +found_it: if ( copy_to_user( argp, map, sizeof(*map) ) ) return -EFAULT; if ( map->type != _DRM_SHM ) { @@ -252,6 +358,12 @@ return -EINVAL; } map = r_list->map; + /* Register and framebuffer maps are permanent */ + if ((map->type == _DRM_REGISTERS) || + (map->type == _DRM_FRAME_BUFFER)) { + up(&dev->struct_sem); + return 0; + } list_del(list); drm_free(list, sizeof(*list), DRM_MEM_MAPS); @@ -263,16 +375,6 @@ switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: - if (drm_core_has_MTRR(dev)) { - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } - } - drm_ioremapfree(map->handle, map->size, dev); break; case _DRM_SHM: vfree(map->handle); Index: drivers/char/drm/drm_drv.c =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_drv.c (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_drv.c (mode:100644) @@ -198,17 +198,7 @@ switch ( map->type ) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: - if (drm_core_has_MTRR(dev)) { - if ( map->mtrr >= 0 ) { - int retcode; - retcode = mtrr_del( map->mtrr, - map->offset, - map->size ); - DRM_DEBUG( "mtrr_del=%d\n", retcode ); - } - } - drm_ioremapfree( map->handle, map->size, dev ); - break; + continue; case _DRM_SHM: vfree(map->handle); break; @@ -231,8 +221,6 @@ list_del( list ); drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS); } - drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); - dev->maplist = NULL; } if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) { @@ -313,6 +301,10 @@ */ static void drm_cleanup( drm_device_t *dev ) { + drm_map_t *map; + drm_map_list_t *r_list; + struct list_head *list, *list_next; + DRM_DEBUG( "\n" ); if (!dev) { @@ -320,7 +312,47 @@ return; } - drm_takedown( dev ); + drm_takedown( dev ); + + if (dev->maplist) { + list_for_each_safe(list, list_next, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + + if ((map = r_list->map)) { + switch (map->type) { + case _DRM_REGISTERS: + drm_ioremapfree(map->handle, map->size, + dev); + break; + + case _DRM_FRAME_BUFFER: + if (drm_core_has_MTRR(dev)) { + if (map->mtrr >= 0) { + int retcode; + retcode = + mtrr_del(map->mtrr, + map-> + offset, + map->size); + DRM_DEBUG("mtrr_del=%d\n", + retcode); + } + } + break; + case _DRM_SHM: + case _DRM_AGP: + case _DRM_SCATTER_GATHER: + DRM_DEBUG("Extra maplist item\n"); + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + list_del(list); + drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS); + } + drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); + dev->maplist = NULL; + } drm_ctxbitmap_cleanup( dev ); Index: drivers/char/drm/drm_fops.c =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_fops.c (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_fops.c (mode:100644) @@ -69,12 +69,6 @@ dev->magiclist[i].tail = NULL; } - dev->maplist = drm_alloc(sizeof(*dev->maplist), - DRM_MEM_MAPS); - if(dev->maplist == NULL) return -ENOMEM; - memset(dev->maplist, 0, sizeof(*dev->maplist)); - INIT_LIST_HEAD(&dev->maplist->head); - dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); if(dev->ctxlist == NULL) return -ENOMEM; Index: drivers/char/drm/drm_stub.c =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_stub.c (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_stub.c (mode:100644) @@ -75,6 +75,12 @@ dev->pci_func = PCI_FUNC(pdev->devfn); dev->irq = pdev->irq; + dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); + if(dev->maplist == NULL) + return -ENOMEM; + INIT_LIST_HEAD(&dev->maplist->head); + + /* the DRM has 6 basic counters */ dev->counters = 6; dev->types[0] = _DRM_STAT_LOCK; Index: drivers/char/drm/radeon_cp.c =================================================================== --- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/radeon_cp.c (mode:100644) +++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/radeon_cp.c (mode:100644) @@ -2045,6 +2045,18 @@ /* all other chips have no hierarchical z buffer */ break; } + + ret = drm_initmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), 2, _DRM_REGISTERS, 0); + if (ret != 0) + return ret; + + ret = drm_initmap(dev, drm_get_resource_start(dev, 0), + drm_get_resource_len(dev, 0), 0, _DRM_FRAME_BUFFER, + _DRM_WRITE_COMBINING); + if (ret != 0) + return ret; + return ret; }