Commit 9c8da5eb authored by Dave Airlie's avatar Dave Airlie Committed by Dave Airlie

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: default avatarDavid Airlie <airlied@linux.ie>
parent d59431bf
...@@ -527,6 +527,12 @@ typedef struct drm_sigdata { ...@@ -527,6 +527,12 @@ typedef struct drm_sigdata {
drm_hw_lock_t *lock; drm_hw_lock_t *lock;
} drm_sigdata_t; } drm_sigdata_t;
typedef struct drm_dma_handle {
dma_addr_t busaddr;
void *vaddr;
size_t size;
} drm_dma_handle_t;
/** /**
* Mappings list * Mappings list
*/ */
...@@ -978,12 +984,10 @@ extern int drm_ati_pcigart_cleanup(drm_device_t *dev, ...@@ -978,12 +984,10 @@ extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
unsigned long addr, unsigned long addr,
dma_addr_t bus_addr); dma_addr_t bus_addr);
extern void *drm_pci_alloc(drm_device_t * dev, size_t size, extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size,
size_t align, dma_addr_t maxaddr, size_t align, dma_addr_t maxaddr);
dma_addr_t * busaddr); 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);
extern void drm_pci_free(drm_device_t * dev, size_t size,
void *vaddr, dma_addr_t busaddr);
/* sysfs support (drm_sysfs.c) */ /* sysfs support (drm_sysfs.c) */
struct drm_sysfs_class; struct drm_sysfs_class;
......
...@@ -90,6 +90,7 @@ int drm_addmap( struct inode *inode, struct file *filp, ...@@ -90,6 +90,7 @@ int drm_addmap( struct inode *inode, struct file *filp,
drm_map_t *map; drm_map_t *map;
drm_map_t __user *argp = (void __user *)arg; drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list; drm_map_list_t *list;
drm_dma_handle_t *dmah;
if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
...@@ -181,21 +182,19 @@ int drm_addmap( struct inode *inode, struct file *filp, ...@@ -181,21 +182,19 @@ int drm_addmap( struct inode *inode, struct file *filp,
map->offset += dev->sg->handle; map->offset += dev->sg->handle;
break; break;
case _DRM_CONSISTENT: case _DRM_CONSISTENT:
{
/* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G, /* 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 * casting it down to 32 bits is no problem, but we
* need to point to a 64bit variable first. */ * need to point to a 64bit variable first. */
dma_addr_t bus_addr; dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
map->handle = drm_pci_alloc(dev, map->size, map->size, if (!dmah) {
0xffffffffUL, &bus_addr);
map->offset = (unsigned long)bus_addr;
if (!map->handle) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -ENOMEM; return -ENOMEM;
} }
map->handle = dmah->vaddr;
map->offset = (unsigned long)dmah->busaddr;
kfree(dmah);
break; break;
}
default: default:
drm_free( map, sizeof(*map), DRM_MEM_MAPS ); drm_free( map, sizeof(*map), DRM_MEM_MAPS );
return -EINVAL; return -EINVAL;
...@@ -286,6 +285,8 @@ int drm_rmmap(struct inode *inode, struct file *filp, ...@@ -286,6 +285,8 @@ int drm_rmmap(struct inode *inode, struct file *filp,
} }
if(!found_maps) { if(!found_maps) {
drm_dma_handle_t dmah;
switch (map->type) { switch (map->type) {
case _DRM_REGISTERS: case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER: case _DRM_FRAME_BUFFER:
...@@ -307,7 +308,10 @@ int drm_rmmap(struct inode *inode, struct file *filp, ...@@ -307,7 +308,10 @@ int drm_rmmap(struct inode *inode, struct file *filp,
case _DRM_SCATTER_GATHER: case _DRM_SCATTER_GATHER:
break; break;
case _DRM_CONSISTENT: 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; break;
} }
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
......
...@@ -198,6 +198,8 @@ int drm_takedown( drm_device_t *dev ) ...@@ -198,6 +198,8 @@ int drm_takedown( drm_device_t *dev )
r_list = (drm_map_list_t *)list; r_list = (drm_map_list_t *)list;
if ( ( map = r_list->map ) ) { if ( ( map = r_list->map ) ) {
drm_dma_handle_t dmah;
switch ( map->type ) { switch ( map->type ) {
case _DRM_REGISTERS: case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER: case _DRM_FRAME_BUFFER:
...@@ -229,8 +231,10 @@ int drm_takedown( drm_device_t *dev ) ...@@ -229,8 +231,10 @@ int drm_takedown( drm_device_t *dev )
} }
break; break;
case _DRM_CONSISTENT: case _DRM_CONSISTENT:
drm_pci_free(dev, map->size, dmah.vaddr = map->handle;
map->handle, map->offset); dmah.busaddr = map->offset;
dmah.size = map->size;
__drm_pci_free(dev, &dmah);
break; break;
} }
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
......
...@@ -46,10 +46,10 @@ ...@@ -46,10 +46,10 @@
/** /**
* \brief Allocate a PCI consistent memory block, for DMA. * \brief Allocate a PCI consistent memory block, for DMA.
*/ */
void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
dma_addr_t maxaddr, dma_addr_t * busaddr) dma_addr_t maxaddr)
{ {
void *address; drm_dma_handle_t *dmah;
#if DRM_DEBUG_MEMORY #if DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA; int area = DRM_MEM_DMA;
...@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, ...@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
return NULL; 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 DRM_DEBUG_MEMORY
if (address == NULL) { if (dmah->vaddr == NULL) {
spin_lock(&drm_mem_lock); spin_lock(&drm_mem_lock);
++drm_mem_stats[area].fail_count; ++drm_mem_stats[area].fail_count;
spin_unlock(&drm_mem_lock); spin_unlock(&drm_mem_lock);
kfree(dmah);
return NULL; return NULL;
} }
...@@ -90,21 +96,25 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, ...@@ -90,21 +96,25 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
drm_ram_used += size; drm_ram_used += size;
spin_unlock(&drm_mem_lock); spin_unlock(&drm_mem_lock);
#else #else
if (address == NULL) if (dmah->vaddr == NULL) {
kfree(dmah);
return NULL; return NULL;
}
#endif #endif
memset(address, 0, size); memset(dmah->vaddr, 0, size);
return address; return dmah;
} }
EXPORT_SYMBOL(drm_pci_alloc); 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 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 #if DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA; int area = DRM_MEM_DMA;
...@@ -112,12 +122,13 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) ...@@ -112,12 +122,13 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
int free_count; int free_count;
#endif #endif
if (!vaddr) { if (!dmah->vaddr) {
#if DRM_DEBUG_MEMORY #if DRM_DEBUG_MEMORY
DRM_MEM_ERROR(area, "Attempt to free address 0\n"); DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif #endif
} else { } else {
pci_free_consistent(dev->pdev, size, vaddr, busaddr); pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
dmah->busaddr);
} }
#if DRM_DEBUG_MEMORY #if DRM_DEBUG_MEMORY
...@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) ...@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
#endif #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); EXPORT_SYMBOL(drm_pci_free);
/*@}*/ /*@}*/
...@@ -210,6 +210,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) ...@@ -210,6 +210,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
} }
if(!found_maps) { if(!found_maps) {
drm_dma_handle_t dmah;
switch (map->type) { switch (map->type) {
case _DRM_REGISTERS: case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER: case _DRM_FRAME_BUFFER:
...@@ -229,8 +231,10 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) ...@@ -229,8 +231,10 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER: case _DRM_SCATTER_GATHER:
break; break;
case _DRM_CONSISTENT: case _DRM_CONSISTENT:
drm_pci_free(dev, map->size, map->handle, dmah.vaddr = map->handle;
map->offset); dmah.busaddr = map->offset;
dmah.size = map->size;
__drm_pci_free(dev, &dmah);
break; break;
} }
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
......
...@@ -95,9 +95,8 @@ static int i915_dma_cleanup(drm_device_t * dev) ...@@ -95,9 +95,8 @@ static int i915_dma_cleanup(drm_device_t * dev)
drm_core_ioremapfree( &dev_priv->ring.map, dev); drm_core_ioremapfree( &dev_priv->ring.map, dev);
} }
if (dev_priv->hw_status_page) { if (dev_priv->status_page_dmah) {
drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page, drm_pci_free(dev, dev_priv->status_page_dmah);
dev_priv->dma_status_page);
/* Need to rewrite hardware status page */ /* Need to rewrite hardware status page */
I915_WRITE(0x02080, 0x1ffff000); I915_WRITE(0x02080, 0x1ffff000);
} }
...@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev, ...@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->allow_batchbuffer = 1; dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */ /* Program Hardware Status Page */
dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
0xffffffff, 0xffffffff);
&dev_priv->dma_status_page);
if (!dev_priv->hw_status_page) { if (!dev_priv->status_page_dmah) {
dev->dev_private = (void *)dev_priv; dev->dev_private = (void *)dev_priv;
i915_dma_cleanup(dev); i915_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n"); DRM_ERROR("Can not allocate hardware status page\n");
return DRM_ERR(ENOMEM); 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); memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
......
...@@ -79,9 +79,10 @@ typedef struct drm_i915_private { ...@@ -79,9 +79,10 @@ typedef struct drm_i915_private {
drm_i915_sarea_t *sarea_priv; drm_i915_sarea_t *sarea_priv;
drm_i915_ring_buffer_t ring; drm_i915_ring_buffer_t ring;
drm_dma_handle_t *status_page_dmah;
void *hw_status_page; void *hw_status_page;
unsigned long counter;
dma_addr_t dma_status_page; dma_addr_t dma_status_page;
unsigned long counter;
int back_offset; int back_offset;
int front_offset; int front_offset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment