Please apply this to the DRI codebase. Also forwarding it to XFree86.
-- Mike A. Harris Shipping/mailing address: OS Systems Engineer 190 Pittsburgh Ave., Sault Ste. Marie, XFree86 maintainer Ontario, Canada, P6C 5B3 Red Hat Inc. http://www.redhat.com ftp://people.redhat.com/mharris ---------- Forwarded message ---------- Date: Tue, 9 Jul 2002 09:02:48 -0400 From: Arjan van de Ven <[EMAIL PROTECTED]> To: Mike A. Harris <[EMAIL PROTECTED]> Content-Type: text/plain; charset=us-ascii Subject: DRM patch for i810/i830 memory allocation Hi, The patch below makes the i810 and i830 drm kernel module use the PCI DMA mapping API instead of an ad-hoc allocator for allocating the page that is used to communicate between driver and card. The ad-hoc allocator doesn't actually work well in practice (I get quite a few bugreports about it) and the PCI DMA API should be used regardless (it actually works cross-platform) Greetings, Arjan van de Ven diff -urN linux/drivers/char/drm.org/i810_dma.c linux/drivers/char/drm/i810_dma.c --- linux/drivers/char/drm.org/i810_dma.c Fri Jul 5 16:12:21 2002 +++ linux/drivers/char/drm/i810_dma.c Fri Jul 5 17:15:08 2002 @@ -258,30 +258,6 @@ return retcode; } -static unsigned long i810_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - - get_page(virt_to_page(address)); - LockPage(virt_to_page(address)); - - return address; -} - -static void i810_free_page(drm_device_t *dev, unsigned long page) -{ - if (page) { - struct page *p = virt_to_page(page); - put_page(p); - UnlockPage(p); - free_page(page); - } -} - static int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -296,7 +272,8 @@ dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i810_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, +dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I810_WRITE(0x02080, 0x1ffff000); } @@ -462,7 +439,8 @@ dev_priv->zi1 = init->depth_offset | init->pitch_bits; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i810_alloc_page(dev); + dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); @@ -472,7 +450,7 @@ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I810_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff -urN linux/drivers/char/drm.org/i810_drv.h linux/drivers/char/drm/i810_drv.h --- linux/drivers/char/drm.org/i810_drv.h Fri Jul 5 16:12:02 2002 +++ linux/drivers/char/drm/i810_drv.h Fri Jul 5 17:10:41 2002 @@ -63,6 +63,7 @@ unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; atomic_t flush_done; wait_queue_head_t flush_queue; /* Processes waiting until flush */ diff -u linux/drivers/char/drm.org/i830_dma.c linux/drivers/char/drm/i830_dma.c --- linux/drivers/char/drm.org/i830_dma.c Sat Jul 6 11:57:25 2002 +++ linux/drivers/char/drm/i830_dma.c Sat Jul 6 15:18:14 2002 @@ -283,31 +283,6 @@ return retcode; } -static unsigned long i830_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - - atomic_inc(&virt_to_page(address)->count); - set_bit(PG_locked, &virt_to_page(address)->flags); - - return address; -} - -static void i830_free_page(drm_device_t *dev, unsigned long addr) -{ - if (addr) { - struct page *page = virt_to_page(addr); - - put_page(page); - UnlockPage(page); - free_page(addr); - } -} - static int i830_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -322,7 +297,8 @@ dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i830_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + dev_priv->hw_status_page, dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I830_WRITE(0x02080, 0x1ffff000); } @@ -496,7 +472,8 @@ dev_priv->depth_pitch = init->depth_pitch; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i830_alloc_page(dev); + dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); @@ -506,7 +483,7 @@ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I830_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ diff -u linux/drivers/char/drm.org/i830_drv.h linux/drivers/char/drm/i830_drv.h --- linux/drivers/char/drm.org/i830_drv.h Sat Jul 6 11:57:17 2002 +++ linux/drivers/char/drm/i830_drv.h Sat Jul 6 15:15:42 2002 @@ -63,6 +63,8 @@ unsigned long hw_status_page; unsigned long counter; + + dma_addr_t dma_status_page; atomic_t flush_done; wait_queue_head_t flush_queue; /* Processes waiting until flush */ ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Stuff, things, and much much more. http://thinkgeek.com/sf _______________________________________________ Dri-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/dri-devel