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>
spinlock_t lock;
} 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.
*/
drm_buf_t *buflist; /**< buffer list */
int seg_count;
int page_order;
- unsigned long *seglist;
+ drm_dma_handle_t **seglist;
drm_freelist_t freelist;
} drm_buf_entry_t;
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
*/
if (entry->seg_count) {
for (i = 0; i < entry->seg_count; i++) {
if (entry->seglist[i]) {
- drm_free_pages(entry->seglist[i],
- entry->page_order, DRM_MEM_DMA);
+ drm_pci_free(dev, entry->seglist[i]);
}
}
drm_free(entry->seglist,
int total;
int page_order;
drm_buf_entry_t *entry;
- unsigned long page;
+ drm_dma_handle_t *dmah;
drm_buf_t *buf;
int alignment;
unsigned long offset;
page_count = 0;
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. */
entry->buf_count = count;
entry->seg_count = count;
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- entry->seglist[entry->seg_count++] = page;
+ entry->seglist[entry->seg_count++] = dmah;
for (i = 0; i < (1 << page_order); i++) {
DRM_DEBUG("page %d @ 0x%08lx\n",
dma->page_count + page_count,
- page + PAGE_SIZE * i);
+ (unsigned long)dmah->vaddr + PAGE_SIZE * i);
temp_pagelist[dma->page_count + page_count++]
- = page + PAGE_SIZE * i;
+ = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
}
for (offset = 0;
offset + size <= total && entry->buf_count < count;
buf->order = order;
buf->used = 0;
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->waiting = 0;
buf->pending = 0;
dma->bufs[i].seg_count);
for (j = 0; j < dma->bufs[i].seg_count; j++) {
if (dma->bufs[i].seglist[j]) {
- drm_free_pages(dma->bufs[i].seglist[j],
- dma->bufs[i].page_order,
- DRM_MEM_DMA);
+ drm_pci_free(dev, dma->bufs[i].seglist[j]);
}
}
drm_free(dma->bufs[i].seglist,
dma_addr_t maxaddr)
{
drm_dma_handle_t *dmah;
+#if 1
+ unsigned long addr;
+ size_t sz;
+#endif
#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
return NULL;
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
if (dmah->vaddr == NULL) {
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;
}
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.
*/
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
int area = DRM_MEM_DMA;
int alloc_count;
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif
} else {
- pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
- dmah->busaddr);
+ /* 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);
}
#ifdef DRM_DEBUG_MEMORY