1c0e09200SDave Airlie /* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */ 2c0e09200SDave Airlie /** 3c0e09200SDave Airlie * \file drm_pci.c 4c0e09200SDave Airlie * \brief Functions and ioctls to manage PCI memory 5c0e09200SDave Airlie * 6c0e09200SDave Airlie * \warning These interfaces aren't stable yet. 7c0e09200SDave Airlie * 8c0e09200SDave Airlie * \todo Implement the remaining ioctl's for the PCI pools. 9c0e09200SDave Airlie * \todo The wrappers here are so thin that they would be better off inlined.. 10c0e09200SDave Airlie * 11c0e09200SDave Airlie * \author José Fonseca <jrfonseca@tungstengraphics.com> 12c0e09200SDave Airlie * \author Leif Delgass <ldelgass@retinalburn.net> 13c0e09200SDave Airlie */ 14c0e09200SDave Airlie 15c0e09200SDave Airlie /* 16c0e09200SDave Airlie * Copyright 2003 José Fonseca. 17c0e09200SDave Airlie * Copyright 2003 Leif Delgass. 18c0e09200SDave Airlie * All Rights Reserved. 19c0e09200SDave Airlie * 20c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 21c0e09200SDave Airlie * copy of this software and associated documentation files (the "Software"), 22c0e09200SDave Airlie * to deal in the Software without restriction, including without limitation 23c0e09200SDave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 24c0e09200SDave Airlie * and/or sell copies of the Software, and to permit persons to whom the 25c0e09200SDave Airlie * Software is furnished to do so, subject to the following conditions: 26c0e09200SDave Airlie * 27c0e09200SDave Airlie * The above copyright notice and this permission notice (including the next 28c0e09200SDave Airlie * paragraph) shall be included in all copies or substantial portions of the 29c0e09200SDave Airlie * Software. 30c0e09200SDave Airlie * 31c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32c0e09200SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33c0e09200SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34c0e09200SDave Airlie * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35c0e09200SDave Airlie * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36c0e09200SDave Airlie * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37c0e09200SDave Airlie */ 38c0e09200SDave Airlie 39c0e09200SDave Airlie #include <linux/pci.h> 40c0e09200SDave Airlie #include <linux/dma-mapping.h> 41c0e09200SDave Airlie #include "drmP.h" 42c0e09200SDave Airlie 43c0e09200SDave Airlie /**********************************************************************/ 44c0e09200SDave Airlie /** \name PCI memory */ 45c0e09200SDave Airlie /*@{*/ 46c0e09200SDave Airlie 47c0e09200SDave Airlie /** 48c0e09200SDave Airlie * \brief Allocate a PCI consistent memory block, for DMA. 49c0e09200SDave Airlie */ 50c0e09200SDave Airlie drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align, 51c0e09200SDave Airlie dma_addr_t maxaddr) 52c0e09200SDave Airlie { 53c0e09200SDave Airlie drm_dma_handle_t *dmah; 54c0e09200SDave Airlie #if 1 55c0e09200SDave Airlie unsigned long addr; 56c0e09200SDave Airlie size_t sz; 57c0e09200SDave Airlie #endif 58c0e09200SDave Airlie 59c0e09200SDave Airlie /* pci_alloc_consistent only guarantees alignment to the smallest 60c0e09200SDave Airlie * PAGE_SIZE order which is greater than or equal to the requested size. 61c0e09200SDave Airlie * Return NULL here for now to make sure nobody tries for larger alignment 62c0e09200SDave Airlie */ 63c0e09200SDave Airlie if (align > size) 64c0e09200SDave Airlie return NULL; 65c0e09200SDave Airlie 66c0e09200SDave Airlie if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) { 67c0e09200SDave Airlie DRM_ERROR("Setting pci dma mask failed\n"); 68c0e09200SDave Airlie return NULL; 69c0e09200SDave Airlie } 70c0e09200SDave Airlie 71c0e09200SDave Airlie dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); 72c0e09200SDave Airlie if (!dmah) 73c0e09200SDave Airlie return NULL; 74c0e09200SDave Airlie 75c0e09200SDave Airlie dmah->size = size; 76c0e09200SDave Airlie dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); 77c0e09200SDave Airlie 78c0e09200SDave Airlie if (dmah->vaddr == NULL) { 79c0e09200SDave Airlie kfree(dmah); 80c0e09200SDave Airlie return NULL; 81c0e09200SDave Airlie } 82c0e09200SDave Airlie 83c0e09200SDave Airlie memset(dmah->vaddr, 0, size); 84c0e09200SDave Airlie 85c0e09200SDave Airlie /* XXX - Is virt_to_page() legal for consistent mem? */ 86c0e09200SDave Airlie /* Reserve */ 87c0e09200SDave Airlie for (addr = (unsigned long)dmah->vaddr, sz = size; 88c0e09200SDave Airlie sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { 89c0e09200SDave Airlie SetPageReserved(virt_to_page(addr)); 90c0e09200SDave Airlie } 91c0e09200SDave Airlie 92c0e09200SDave Airlie return dmah; 93c0e09200SDave Airlie } 94c0e09200SDave Airlie 95c0e09200SDave Airlie EXPORT_SYMBOL(drm_pci_alloc); 96c0e09200SDave Airlie 97c0e09200SDave Airlie /** 98c0e09200SDave Airlie * \brief Free a PCI consistent memory block without freeing its descriptor. 99c0e09200SDave Airlie * 100c0e09200SDave Airlie * This function is for internal use in the Linux-specific DRM core code. 101c0e09200SDave Airlie */ 102c0e09200SDave Airlie void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) 103c0e09200SDave Airlie { 104c0e09200SDave Airlie #if 1 105c0e09200SDave Airlie unsigned long addr; 106c0e09200SDave Airlie size_t sz; 107c0e09200SDave Airlie #endif 108c0e09200SDave Airlie 1099a298b2aSEric Anholt if (dmah->vaddr) { 110c0e09200SDave Airlie /* XXX - Is virt_to_page() legal for consistent mem? */ 111c0e09200SDave Airlie /* Unreserve */ 112c0e09200SDave Airlie for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; 113c0e09200SDave Airlie sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { 114c0e09200SDave Airlie ClearPageReserved(virt_to_page(addr)); 115c0e09200SDave Airlie } 116c0e09200SDave Airlie dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, 117c0e09200SDave Airlie dmah->busaddr); 118c0e09200SDave Airlie } 119c0e09200SDave Airlie } 120c0e09200SDave Airlie 121c0e09200SDave Airlie /** 122c0e09200SDave Airlie * \brief Free a PCI consistent memory block 123c0e09200SDave Airlie */ 124c0e09200SDave Airlie void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) 125c0e09200SDave Airlie { 126c0e09200SDave Airlie __drm_pci_free(dev, dmah); 127c0e09200SDave Airlie kfree(dmah); 128c0e09200SDave Airlie } 129c0e09200SDave Airlie 130c0e09200SDave Airlie EXPORT_SYMBOL(drm_pci_free); 131c0e09200SDave Airlie 132c0e09200SDave Airlie /*@}*/ 133