drm: update support for drm pci buffers

The DRM needs to change the drm_pci interface for FreeBSD compatiblity,
this patch introduces the drm_dma_handle_t and uses it in the Linux code.

From: Tonnerre Lombard, Eric Anholt, and Sergey Vlasov
Signed-off-by: David Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 804e622..7e633a9 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -527,6 +527,12 @@
 	drm_hw_lock_t *lock;
 } drm_sigdata_t;
 
+typedef struct drm_dma_handle {
+	dma_addr_t busaddr;
+	void *vaddr;
+	size_t size;
+} drm_dma_handle_t;
+
 /**
  * Mappings list
  */
@@ -978,12 +984,10 @@
 					       unsigned long addr,
 					       dma_addr_t bus_addr);
 
-extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
-			   size_t align, dma_addr_t maxaddr,
-			   dma_addr_t * busaddr);
-
-extern void drm_pci_free(drm_device_t * dev, size_t size,
-			 void *vaddr, dma_addr_t busaddr);
+extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size,
+				       size_t align, dma_addr_t maxaddr);
+extern void __drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
+extern void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
 
 			       /* sysfs support (drm_sysfs.c) */
 struct drm_sysfs_class;
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index eb3cf55..be54efb 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -90,6 +90,7 @@
 	drm_map_t *map;
 	drm_map_t __user *argp = (void __user *)arg;
 	drm_map_list_t *list;
+	drm_dma_handle_t *dmah;
 
 	if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
 
@@ -181,21 +182,19 @@
 		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),
+		 * As we're limiting the address to 2^32-1 (or less),
 		 * 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) {
+		dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+		if (!dmah) {
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 			return -ENOMEM;
 		}
+		map->handle = dmah->vaddr;
+		map->offset = (unsigned long)dmah->busaddr;
+		kfree(dmah);
 		break;
-	}
 	default:
 		drm_free( map, sizeof(*map), DRM_MEM_MAPS );
 		return -EINVAL;
@@ -286,6 +285,8 @@
 	}
 
 	if(!found_maps) {
+		drm_dma_handle_t dmah;
+
 		switch (map->type) {
 		case _DRM_REGISTERS:
 		case _DRM_FRAME_BUFFER:
@@ -307,7 +308,10 @@
 		case _DRM_SCATTER_GATHER:
 			break;
 		case _DRM_CONSISTENT:
-			drm_pci_free(dev, map->size, map->handle, map->offset);
+			dmah.vaddr = map->handle;
+			dmah.busaddr = map->offset;
+			dmah.size = map->size;
+			__drm_pci_free(dev, &dmah);
 			break;
 		}
 		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index f4046c8..ab172ea 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -198,6 +198,8 @@
 			r_list = (drm_map_list_t *)list;
 
 			if ( ( map = r_list->map ) ) {
+				drm_dma_handle_t dmah;
+
 				switch ( map->type ) {
 				case _DRM_REGISTERS:
 				case _DRM_FRAME_BUFFER:
@@ -229,8 +231,10 @@
 					}
 					break;
 				case _DRM_CONSISTENT:
-					drm_pci_free(dev, map->size,
-						     map->handle, map->offset);
+					dmah.vaddr = map->handle;
+					dmah.busaddr = map->offset;
+					dmah.size = map->size;
+					__drm_pci_free(dev, &dmah);
 					break;
 				}
 				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 192e876..3e452e8 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -46,10 +46,10 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
-		    dma_addr_t maxaddr, dma_addr_t * busaddr)
+drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+				dma_addr_t maxaddr)
 {
-	void *address;
+	drm_dma_handle_t *dmah;
 #if DRM_DEBUG_MEMORY
 	int area = DRM_MEM_DMA;
 
@@ -74,13 +74,19 @@
 		return NULL;
 	}
 
-	address = pci_alloc_consistent(dev->pdev, size, busaddr);
+	dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+	if (!dmah)
+		return NULL;
+	
+	dmah->size = size;
+	dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
 
 #if DRM_DEBUG_MEMORY
-	if (address == NULL) {
+	if (dmah->vaddr == NULL) {
 		spin_lock(&drm_mem_lock);
 		++drm_mem_stats[area].fail_count;
 		spin_unlock(&drm_mem_lock);
+		kfree(dmah);
 		return NULL;
 	}
 
@@ -90,21 +96,25 @@
 	drm_ram_used += size;
 	spin_unlock(&drm_mem_lock);
 #else
-	if (address == NULL)
+	if (dmah->vaddr == NULL) {
+		kfree(dmah);
 		return NULL;
+	}
 #endif
 
-	memset(address, 0, size);
+	memset(dmah->vaddr, 0, size);
 
-	return address;
+	return dmah;
 }
 EXPORT_SYMBOL(drm_pci_alloc);
 
 /**
- * \brief Free a PCI consistent memory block.
+ * \brief Free a PCI consistent memory block with freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
  */
 void
-drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
+__drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
 {
 #if DRM_DEBUG_MEMORY
 	int area = DRM_MEM_DMA;
@@ -112,12 +122,13 @@
 	int free_count;
 #endif
 
-	if (!vaddr) {
+	if (!dmah->vaddr) {
 #if DRM_DEBUG_MEMORY
 		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
 #endif
 	} else {
-		pci_free_consistent(dev->pdev, size, vaddr, busaddr);
+		pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
+				    dmah->busaddr);
 	}
 
 #if DRM_DEBUG_MEMORY
@@ -135,6 +146,16 @@
 #endif
 
 }
+
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void
+drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
+{
+	__drm_pci_free(dev, dmah);
+	kfree(dmah);
+}
 EXPORT_SYMBOL(drm_pci_free);
 
 /*@}*/
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 644ec9da..675d239 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -210,6 +210,8 @@
 		}
 
 		if(!found_maps) {
+			drm_dma_handle_t dmah;
+
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
@@ -229,8 +231,10 @@
 			case _DRM_SCATTER_GATHER:
 				break;
 			case _DRM_CONSISTENT:
-				drm_pci_free(dev, map->size, map->handle,
-					     map->offset);
+				dmah.vaddr = map->handle;
+				dmah.busaddr = map->offset;
+				dmah.size = map->size;
+				__drm_pci_free(dev, &dmah);
 				break;
 			}
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index acf9e52..759f229 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -95,9 +95,8 @@
 			drm_core_ioremapfree( &dev_priv->ring.map, dev);
 		}
 
-		if (dev_priv->hw_status_page) {
-			drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
-				     dev_priv->dma_status_page);
+		if (dev_priv->status_page_dmah) {
+			drm_pci_free(dev, dev_priv->status_page_dmah);
 			/* Need to rewrite hardware status page */
 			I915_WRITE(0x02080, 0x1ffff000);
 		}
@@ -174,16 +173,18 @@
 	dev_priv->allow_batchbuffer = 1;
 
 	/* Program Hardware Status Page */
-	dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
-						 0xffffffff, 
-						 &dev_priv->dma_status_page);
+	dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
+						   0xffffffff);
 
-	if (!dev_priv->hw_status_page) {
+	if (!dev_priv->status_page_dmah) {
 		dev->dev_private = (void *)dev_priv;
 		i915_dma_cleanup(dev);
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return DRM_ERR(ENOMEM);
 	}
+	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 9c37d23..9308086 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -79,9 +79,10 @@
 	drm_i915_sarea_t *sarea_priv;
 	drm_i915_ring_buffer_t ring;
 
+	drm_dma_handle_t *status_page_dmah;
 	void *hw_status_page;
-	unsigned long counter;
 	dma_addr_t dma_status_page;
+	unsigned long counter;
 
 	int back_offset;
 	int front_offset;