aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2006-03-19 02:56:12 -0500
committerDave Airlie <airlied@linux.ie>2006-03-19 02:56:12 -0500
commitddf19b973be5a96d77c8467f657fe5bd7d126e0f (patch)
treee7b003b3dad82014b364acde5681956011e67b58
parent60a6dc55b93b3321afa52f650a149fb7e87fa85a (diff)
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>
-rw-r--r--drivers/char/drm/drmP.h14
-rw-r--r--drivers/char/drm/drm_bufs.c20
-rw-r--r--drivers/char/drm/drm_dma.c4
-rw-r--r--drivers/char/drm/drm_pci.c29
4 files changed, 44 insertions, 23 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 107df9fdba4e..dbe952f899c0 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -357,6 +357,12 @@ typedef struct drm_freelist {
357 spinlock_t lock; 357 spinlock_t lock;
358} drm_freelist_t; 358} drm_freelist_t;
359 359
360typedef struct drm_dma_handle {
361 dma_addr_t busaddr;
362 void *vaddr;
363 size_t size;
364} drm_dma_handle_t;
365
360/** 366/**
361 * Buffer entry. There is one of this for each buffer size order. 367 * Buffer entry. There is one of this for each buffer size order.
362 */ 368 */
@@ -366,7 +372,7 @@ typedef struct drm_buf_entry {
366 drm_buf_t *buflist; /**< buffer list */ 372 drm_buf_t *buflist; /**< buffer list */
367 int seg_count; 373 int seg_count;
368 int page_order; 374 int page_order;
369 unsigned long *seglist; 375 drm_dma_handle_t **seglist;
370 376
371 drm_freelist_t freelist; 377 drm_freelist_t freelist;
372} drm_buf_entry_t; 378} drm_buf_entry_t;
@@ -483,12 +489,6 @@ typedef struct drm_sigdata {
483 drm_hw_lock_t *lock; 489 drm_hw_lock_t *lock;
484} drm_sigdata_t; 490} drm_sigdata_t;
485 491
486typedef struct drm_dma_handle {
487 dma_addr_t busaddr;
488 void *vaddr;
489 size_t size;
490} drm_dma_handle_t;
491
492/** 492/**
493 * Mappings list 493 * Mappings list
494 */ 494 */
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index e2637b4d51de..8a9cf12e6183 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
474 if (entry->seg_count) { 474 if (entry->seg_count) {
475 for (i = 0; i < entry->seg_count; i++) { 475 for (i = 0; i < entry->seg_count; i++) {
476 if (entry->seglist[i]) { 476 if (entry->seglist[i]) {
477 drm_free_pages(entry->seglist[i], 477 drm_pci_free(dev, entry->seglist[i]);
478 entry->page_order, DRM_MEM_DMA);
479 } 478 }
480 } 479 }
481 drm_free(entry->seglist, 480 drm_free(entry->seglist,
@@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
678 int total; 677 int total;
679 int page_order; 678 int page_order;
680 drm_buf_entry_t *entry; 679 drm_buf_entry_t *entry;
681 unsigned long page; 680 drm_dma_handle_t *dmah;
682 drm_buf_t *buf; 681 drm_buf_t *buf;
683 int alignment; 682 int alignment;
684 unsigned long offset; 683 unsigned long offset;
@@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
781 page_count = 0; 780 page_count = 0;
782 781
783 while (entry->buf_count < count) { 782 while (entry->buf_count < count) {
784 page = drm_alloc_pages(page_order, DRM_MEM_DMA); 783
785 if (!page) { 784 dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
785
786 if (!dmah) {
786 /* Set count correctly so we free the proper amount. */ 787 /* Set count correctly so we free the proper amount. */
787 entry->buf_count = count; 788 entry->buf_count = count;
788 entry->seg_count = count; 789 entry->seg_count = count;
@@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
794 atomic_dec(&dev->buf_alloc); 795 atomic_dec(&dev->buf_alloc);
795 return -ENOMEM; 796 return -ENOMEM;
796 } 797 }
797 entry->seglist[entry->seg_count++] = page; 798 entry->seglist[entry->seg_count++] = dmah;
798 for (i = 0; i < (1 << page_order); i++) { 799 for (i = 0; i < (1 << page_order); i++) {
799 DRM_DEBUG("page %d @ 0x%08lx\n", 800 DRM_DEBUG("page %d @ 0x%08lx\n",
800 dma->page_count + page_count, 801 dma->page_count + page_count,
801 page + PAGE_SIZE * i); 802 (unsigned long)dmah->vaddr + PAGE_SIZE * i);
802 temp_pagelist[dma->page_count + page_count++] 803 temp_pagelist[dma->page_count + page_count++]
803 = page + PAGE_SIZE * i; 804 = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
804 } 805 }
805 for (offset = 0; 806 for (offset = 0;
806 offset + size <= total && entry->buf_count < count; 807 offset + size <= total && entry->buf_count < count;
@@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
811 buf->order = order; 812 buf->order = order;
812 buf->used = 0; 813 buf->used = 0;
813 buf->offset = (dma->byte_count + byte_count + offset); 814 buf->offset = (dma->byte_count + byte_count + offset);
814 buf->address = (void *)(page + offset); 815 buf->address = (void *)(dmah->vaddr + offset);
816 buf->bus_address = dmah->busaddr + offset;
815 buf->next = NULL; 817 buf->next = NULL;
816 buf->waiting = 0; 818 buf->waiting = 0;
817 buf->pending = 0; 819 buf->pending = 0;
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 2afab95ca036..892db7096986 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev)
85 dma->bufs[i].seg_count); 85 dma->bufs[i].seg_count);
86 for (j = 0; j < dma->bufs[i].seg_count; j++) { 86 for (j = 0; j < dma->bufs[i].seg_count; j++) {
87 if (dma->bufs[i].seglist[j]) { 87 if (dma->bufs[i].seglist[j]) {
88 drm_free_pages(dma->bufs[i].seglist[j], 88 drm_pci_free(dev, dma->bufs[i].seglist[j]);
89 dma->bufs[i].page_order,
90 DRM_MEM_DMA);
91 } 89 }
92 } 90 }
93 drm_free(dma->bufs[i].seglist, 91 drm_free(dma->bufs[i].seglist,
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 1fd7ff164817..b28ca9cea8a2 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
50 dma_addr_t maxaddr) 50 dma_addr_t maxaddr)
51{ 51{
52 drm_dma_handle_t *dmah; 52 drm_dma_handle_t *dmah;
53#if 1
54 unsigned long addr;
55 size_t sz;
56#endif
53#ifdef DRM_DEBUG_MEMORY 57#ifdef DRM_DEBUG_MEMORY
54 int area = DRM_MEM_DMA; 58 int area = DRM_MEM_DMA;
55 59
@@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
79 return NULL; 83 return NULL;
80 84
81 dmah->size = size; 85 dmah->size = size;
82 dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); 86 dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
83 87
84#ifdef DRM_DEBUG_MEMORY 88#ifdef DRM_DEBUG_MEMORY
85 if (dmah->vaddr == NULL) { 89 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,
104 108
105 memset(dmah->vaddr, 0, size); 109 memset(dmah->vaddr, 0, size);
106 110
111 /* XXX - Is virt_to_page() legal for consistent mem? */
112 /* Reserve */
113 for (addr = (unsigned long)dmah->vaddr, sz = size;
114 sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
115 SetPageReserved(virt_to_page(addr));
116 }
117
107 return dmah; 118 return dmah;
108} 119}
109 120
110EXPORT_SYMBOL(drm_pci_alloc); 121EXPORT_SYMBOL(drm_pci_alloc);
111 122
112/** 123/**
113 * \brief Free a PCI consistent memory block with freeing its descriptor. 124 * \brief Free a PCI consistent memory block without freeing its descriptor.
114 * 125 *
115 * This function is for internal use in the Linux-specific DRM core code. 126 * This function is for internal use in the Linux-specific DRM core code.
116 */ 127 */
117void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) 128void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
118{ 129{
130#if 1
131 unsigned long addr;
132 size_t sz;
133#endif
119#ifdef DRM_DEBUG_MEMORY 134#ifdef DRM_DEBUG_MEMORY
120 int area = DRM_MEM_DMA; 135 int area = DRM_MEM_DMA;
121 int alloc_count; 136 int alloc_count;
@@ -127,8 +142,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
127 DRM_MEM_ERROR(area, "Attempt to free address 0\n"); 142 DRM_MEM_ERROR(area, "Attempt to free address 0\n");
128#endif 143#endif
129 } else { 144 } else {
130 pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, 145 /* XXX - Is virt_to_page() legal for consistent mem? */
131 dmah->busaddr); 146 /* Unreserve */
147 for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
148 sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
149 ClearPageReserved(virt_to_page(addr));
150 }
151 dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
152 dmah->busaddr);
132 } 153 }
133 154
134#ifdef DRM_DEBUG_MEMORY 155#ifdef DRM_DEBUG_MEMORY