فهرست منبع

drm: add _DRM_CONSISTENT map type

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>
Dave Airlie 20 سال پیش
والد
کامیت
2d0f9eaff8
5فایلهای تغییر یافته به همراه40 افزوده شده و 7 حذف شده
  1. 2 1
      drivers/char/drm/drm.h
  2. 19 1
      drivers/char/drm/drm_bufs.c
  3. 4 0
      drivers/char/drm/drm_drv.c
  4. 8 5
      drivers/char/drm/drm_proc.c
  5. 7 0
      drivers/char/drm/drm_vm.c

+ 2 - 1
drivers/char/drm/drm.h

@@ -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;
 
 

+ 19 - 1
drivers/char/drm/drm_bufs.c

@@ -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);
 	}

+ 4 - 0
drivers/char/drm/drm_drv.c

@@ -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);
 			}

+ 8 - 5
drivers/char/drm/drm_proc.c

@@ -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,

+ 7 - 0
drivers/char/drm/drm_vm.c

@@ -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