xref: /openbmc/linux/drivers/gpu/drm/drm_pci.c (revision 9a298b2a)
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