drm: fixup PCI DMA support
This patch makes the PCI support use the correct Linux interfaces finally. Tested in DRM CVS on PCI MGA card. Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
parent
60a6dc55b9
commit
ddf19b973b
@ -357,6 +357,12 @@ typedef struct drm_freelist {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
} drm_freelist_t;
|
} drm_freelist_t;
|
||||||
|
|
||||||
|
typedef struct drm_dma_handle {
|
||||||
|
dma_addr_t busaddr;
|
||||||
|
void *vaddr;
|
||||||
|
size_t size;
|
||||||
|
} drm_dma_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer entry. There is one of this for each buffer size order.
|
* Buffer entry. There is one of this for each buffer size order.
|
||||||
*/
|
*/
|
||||||
@ -366,7 +372,7 @@ typedef struct drm_buf_entry {
|
|||||||
drm_buf_t *buflist; /**< buffer list */
|
drm_buf_t *buflist; /**< buffer list */
|
||||||
int seg_count;
|
int seg_count;
|
||||||
int page_order;
|
int page_order;
|
||||||
unsigned long *seglist;
|
drm_dma_handle_t **seglist;
|
||||||
|
|
||||||
drm_freelist_t freelist;
|
drm_freelist_t freelist;
|
||||||
} drm_buf_entry_t;
|
} drm_buf_entry_t;
|
||||||
@ -483,12 +489,6 @@ 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
|
||||||
*/
|
*/
|
||||||
|
@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
|
|||||||
if (entry->seg_count) {
|
if (entry->seg_count) {
|
||||||
for (i = 0; i < entry->seg_count; i++) {
|
for (i = 0; i < entry->seg_count; i++) {
|
||||||
if (entry->seglist[i]) {
|
if (entry->seglist[i]) {
|
||||||
drm_free_pages(entry->seglist[i],
|
drm_pci_free(dev, entry->seglist[i]);
|
||||||
entry->page_order, DRM_MEM_DMA);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drm_free(entry->seglist,
|
drm_free(entry->seglist,
|
||||||
@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
|
|||||||
int total;
|
int total;
|
||||||
int page_order;
|
int page_order;
|
||||||
drm_buf_entry_t *entry;
|
drm_buf_entry_t *entry;
|
||||||
unsigned long page;
|
drm_dma_handle_t *dmah;
|
||||||
drm_buf_t *buf;
|
drm_buf_t *buf;
|
||||||
int alignment;
|
int alignment;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
|
|||||||
page_count = 0;
|
page_count = 0;
|
||||||
|
|
||||||
while (entry->buf_count < count) {
|
while (entry->buf_count < count) {
|
||||||
page = drm_alloc_pages(page_order, DRM_MEM_DMA);
|
|
||||||
if (!page) {
|
dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
|
||||||
|
|
||||||
|
if (!dmah) {
|
||||||
/* Set count correctly so we free the proper amount. */
|
/* Set count correctly so we free the proper amount. */
|
||||||
entry->buf_count = count;
|
entry->buf_count = count;
|
||||||
entry->seg_count = count;
|
entry->seg_count = count;
|
||||||
@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
|
|||||||
atomic_dec(&dev->buf_alloc);
|
atomic_dec(&dev->buf_alloc);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
entry->seglist[entry->seg_count++] = page;
|
entry->seglist[entry->seg_count++] = dmah;
|
||||||
for (i = 0; i < (1 << page_order); i++) {
|
for (i = 0; i < (1 << page_order); i++) {
|
||||||
DRM_DEBUG("page %d @ 0x%08lx\n",
|
DRM_DEBUG("page %d @ 0x%08lx\n",
|
||||||
dma->page_count + page_count,
|
dma->page_count + page_count,
|
||||||
page + PAGE_SIZE * i);
|
(unsigned long)dmah->vaddr + PAGE_SIZE * i);
|
||||||
temp_pagelist[dma->page_count + page_count++]
|
temp_pagelist[dma->page_count + page_count++]
|
||||||
= page + PAGE_SIZE * i;
|
= (unsigned long)dmah->vaddr + PAGE_SIZE * i;
|
||||||
}
|
}
|
||||||
for (offset = 0;
|
for (offset = 0;
|
||||||
offset + size <= total && entry->buf_count < count;
|
offset + size <= total && entry->buf_count < count;
|
||||||
@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
|
|||||||
buf->order = order;
|
buf->order = order;
|
||||||
buf->used = 0;
|
buf->used = 0;
|
||||||
buf->offset = (dma->byte_count + byte_count + offset);
|
buf->offset = (dma->byte_count + byte_count + offset);
|
||||||
buf->address = (void *)(page + offset);
|
buf->address = (void *)(dmah->vaddr + offset);
|
||||||
|
buf->bus_address = dmah->busaddr + offset;
|
||||||
buf->next = NULL;
|
buf->next = NULL;
|
||||||
buf->waiting = 0;
|
buf->waiting = 0;
|
||||||
buf->pending = 0;
|
buf->pending = 0;
|
||||||
|
@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev)
|
|||||||
dma->bufs[i].seg_count);
|
dma->bufs[i].seg_count);
|
||||||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||||
if (dma->bufs[i].seglist[j]) {
|
if (dma->bufs[i].seglist[j]) {
|
||||||
drm_free_pages(dma->bufs[i].seglist[j],
|
drm_pci_free(dev, dma->bufs[i].seglist[j]);
|
||||||
dma->bufs[i].page_order,
|
|
||||||
DRM_MEM_DMA);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drm_free(dma->bufs[i].seglist,
|
drm_free(dma->bufs[i].seglist,
|
||||||
|
@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
|
|||||||
dma_addr_t maxaddr)
|
dma_addr_t maxaddr)
|
||||||
{
|
{
|
||||||
drm_dma_handle_t *dmah;
|
drm_dma_handle_t *dmah;
|
||||||
|
#if 1
|
||||||
|
unsigned long addr;
|
||||||
|
size_t sz;
|
||||||
|
#endif
|
||||||
#ifdef DRM_DEBUG_MEMORY
|
#ifdef DRM_DEBUG_MEMORY
|
||||||
int area = DRM_MEM_DMA;
|
int area = DRM_MEM_DMA;
|
||||||
|
|
||||||
@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dmah->size = size;
|
dmah->size = size;
|
||||||
dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
|
dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
|
||||||
|
|
||||||
#ifdef DRM_DEBUG_MEMORY
|
#ifdef DRM_DEBUG_MEMORY
|
||||||
if (dmah->vaddr == NULL) {
|
if (dmah->vaddr == NULL) {
|
||||||
@ -104,18 +108,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
|
|||||||
|
|
||||||
memset(dmah->vaddr, 0, size);
|
memset(dmah->vaddr, 0, size);
|
||||||
|
|
||||||
|
/* XXX - Is virt_to_page() legal for consistent mem? */
|
||||||
|
/* Reserve */
|
||||||
|
for (addr = (unsigned long)dmah->vaddr, sz = size;
|
||||||
|
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||||
|
SetPageReserved(virt_to_page(addr));
|
||||||
|
}
|
||||||
|
|
||||||
return dmah;
|
return dmah;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(drm_pci_alloc);
|
EXPORT_SYMBOL(drm_pci_alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Free a PCI consistent memory block with freeing its descriptor.
|
* \brief Free a PCI consistent memory block without freeing its descriptor.
|
||||||
*
|
*
|
||||||
* This function is for internal use in the Linux-specific DRM core code.
|
* This function is for internal use in the Linux-specific DRM core code.
|
||||||
*/
|
*/
|
||||||
void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
|
void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
unsigned long addr;
|
||||||
|
size_t sz;
|
||||||
|
#endif
|
||||||
#ifdef DRM_DEBUG_MEMORY
|
#ifdef DRM_DEBUG_MEMORY
|
||||||
int area = DRM_MEM_DMA;
|
int area = DRM_MEM_DMA;
|
||||||
int alloc_count;
|
int alloc_count;
|
||||||
@ -127,7 +142,13 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
|
|||||||
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, dmah->size, dmah->vaddr,
|
/* XXX - Is virt_to_page() legal for consistent mem? */
|
||||||
|
/* Unreserve */
|
||||||
|
for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
|
||||||
|
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||||
|
ClearPageReserved(virt_to_page(addr));
|
||||||
|
}
|
||||||
|
dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
|
||||||
dmah->busaddr);
|
dmah->busaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user