drm: add _DRM_CONSISTENT map type
Dave Airlie [Sun, 10 Jul 2005 04:34:13 +0000 (14:34 +1000)]
Added a new DRM map type _DRM_CONSISTENT for consistent PCI memory. It
uses drm_pci_alloc/free for allocating/freeing the memory.

From: Felix Kuhling <fxkuehl@gmx.de>
Signed-off-by: David Airlie <airlied@linux.ie>

drivers/char/drm/drm.h
drivers/char/drm/drm_bufs.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_vm.c

index e8371dd..50c4d98 100644 (file)
@@ -209,7 +209,8 @@ typedef enum drm_map_type {
        _DRM_REGISTERS      = 1,  /**< no caching, no core dump */
        _DRM_SHM            = 2,  /**< shared, cached */
        _DRM_AGP            = 3,  /**< AGP/GART */
-       _DRM_SCATTER_GATHER = 4   /**< Scatter/gather memory for PCI DMA */
+       _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
+       _DRM_CONSISTENT     = 5,  /**< Consistent memory for PCI DMA */
 } drm_map_type_t;
 
 
index 4c6191d..89f301f 100644 (file)
@@ -180,7 +180,22 @@ int drm_addmap( struct inode *inode, struct file *filp,
                }
                map->offset += dev->sg->handle;
                break;
-
+       case _DRM_CONSISTENT: 
+       {
+               /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+                * As we're limit the address to 2^32-1 (or lses),
+                * casting it down to 32 bits is no problem, but we
+                * need to point to a 64bit variable first. */
+               dma_addr_t bus_addr;
+               map->handle = drm_pci_alloc(dev, map->size, map->size,
+                                           0xffffffffUL, &bus_addr);
+               map->offset = (unsigned long)bus_addr;
+               if (!map->handle) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -ENOMEM;
+               }
+               break;
+       }
        default:
                drm_free( map, sizeof(*map), DRM_MEM_MAPS );
                return -EINVAL;
@@ -291,6 +306,9 @@ int drm_rmmap(struct inode *inode, struct file *filp,
                case _DRM_AGP:
                case _DRM_SCATTER_GATHER:
                        break;
+               case _DRM_CONSISTENT:
+                       drm_pci_free(dev, map->size, map->handle, map->offset);
+                       break;
                }
                drm_free(map, sizeof(*map), DRM_MEM_MAPS);
        }
index 3333c25..f4046c8 100644 (file)
@@ -228,6 +228,10 @@ int drm_takedown( drm_device_t *dev )
                                                dev->sg = NULL;
                                        }
                                        break;
+                               case _DRM_CONSISTENT:
+                                       drm_pci_free(dev, map->size,
+                                                    map->handle, map->offset);
+                                       break;
                                }
                                drm_free(map, sizeof(*map), DRM_MEM_MAPS);
                        }
index 4774087..f4154cc 100644 (file)
@@ -210,8 +210,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 
                                /* Hardcoded from _DRM_FRAME_BUFFER,
                                    _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
-                                   _DRM_SCATTER_GATHER. */
-       const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+                                   _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+       const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
        const char   *type;
        int          i;
 
@@ -229,9 +229,12 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
        if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
                r_list = list_entry(list, drm_map_list_t, head);
                map = r_list->map;
-               if(!map) continue;
-               if (map->type < 0 || map->type > 4) type = "??";
-               else                                type = types[map->type];
+               if(!map)
+                       continue;
+               if (map->type < 0 || map->type > 5)
+                       type = "??";
+               else    
+                       type = types[map->type];
                DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
                               i,
                               map->offset,
index 621220f..644ec9d 100644 (file)
@@ -228,6 +228,10 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                        case _DRM_AGP:
                        case _DRM_SCATTER_GATHER:
                                break;
+                       case _DRM_CONSISTENT:
+                               drm_pci_free(dev, map->size, map->handle,
+                                            map->offset);
+                               break;
                        }
                        drm_free(map, sizeof(*map), DRM_MEM_MAPS);
                }
@@ -645,6 +649,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_SHM:
+       case _DRM_CONSISTENT:
+               /* Consistent memory is really like shared memory. It's only
+                * allocate in a different way */
                vma->vm_ops = &drm_vm_shm_ops;
                vma->vm_private_data = (void *)map;
                                /* Don't let this area swap.  Change when