aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_pci.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/drm_pci.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_pci.c')
-rw-r--r--drivers/gpu/drm/drm_pci.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
new file mode 100644
index 000000000000..b55d5bc6ea61
--- /dev/null
+++ b/drivers/gpu/drm/drm_pci.c
@@ -0,0 +1,183 @@
1/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
2/**
3 * \file drm_pci.c
4 * \brief Functions and ioctls to manage PCI memory
5 *
6 * \warning These interfaces aren't stable yet.
7 *
8 * \todo Implement the remaining ioctl's for the PCI pools.
9 * \todo The wrappers here are so thin that they would be better off inlined..
10 *
11 * \author José Fonseca <jrfonseca@tungstengraphics.com>
12 * \author Leif Delgass <ldelgass@retinalburn.net>
13 */
14
15/*
16 * Copyright 2003 José Fonseca.
17 * Copyright 2003 Leif Delgass.
18 * All Rights Reserved.
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice (including the next
28 * paragraph) shall be included in all copies or substantial portions of the
29 * Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
35 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 */
38
39#include <linux/pci.h>
40#include <linux/dma-mapping.h>
41#include "drmP.h"
42
43/**********************************************************************/
44/** \name PCI memory */
45/*@{*/
46
47/**
48 * \brief Allocate a PCI consistent memory block, for DMA.
49 */
50drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
51 dma_addr_t maxaddr)
52{
53 drm_dma_handle_t *dmah;
54#if 1
55 unsigned long addr;
56 size_t sz;
57#endif
58#ifdef DRM_DEBUG_MEMORY
59 int area = DRM_MEM_DMA;
60
61 spin_lock(&drm_mem_lock);
62 if ((drm_ram_used >> PAGE_SHIFT)
63 > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
64 spin_unlock(&drm_mem_lock);
65 return 0;
66 }
67 spin_unlock(&drm_mem_lock);
68#endif
69
70 /* pci_alloc_consistent only guarantees alignment to the smallest
71 * PAGE_SIZE order which is greater than or equal to the requested size.
72 * Return NULL here for now to make sure nobody tries for larger alignment
73 */
74 if (align > size)
75 return NULL;
76
77 if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
78 DRM_ERROR("Setting pci dma mask failed\n");
79 return NULL;
80 }
81
82 dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
83 if (!dmah)
84 return NULL;
85
86 dmah->size = size;
87 dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
88
89#ifdef DRM_DEBUG_MEMORY
90 if (dmah->vaddr == NULL) {
91 spin_lock(&drm_mem_lock);
92 ++drm_mem_stats[area].fail_count;
93 spin_unlock(&drm_mem_lock);
94 kfree(dmah);
95 return NULL;
96 }
97
98 spin_lock(&drm_mem_lock);
99 ++drm_mem_stats[area].succeed_count;
100 drm_mem_stats[area].bytes_allocated += size;
101 drm_ram_used += size;
102 spin_unlock(&drm_mem_lock);
103#else
104 if (dmah->vaddr == NULL) {
105 kfree(dmah);
106 return NULL;
107 }
108#endif
109
110 memset(dmah->vaddr, 0, size);
111
112 /* XXX - Is virt_to_page() legal for consistent mem? */
113 /* Reserve */
114 for (addr = (unsigned long)dmah->vaddr, sz = size;
115 sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
116 SetPageReserved(virt_to_page(addr));
117 }
118
119 return dmah;
120}
121
122EXPORT_SYMBOL(drm_pci_alloc);
123
124/**
125 * \brief Free a PCI consistent memory block without freeing its descriptor.
126 *
127 * This function is for internal use in the Linux-specific DRM core code.
128 */
129void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
130{
131#if 1
132 unsigned long addr;
133 size_t sz;
134#endif
135#ifdef DRM_DEBUG_MEMORY
136 int area = DRM_MEM_DMA;
137 int alloc_count;
138 int free_count;
139#endif
140
141 if (!dmah->vaddr) {
142#ifdef DRM_DEBUG_MEMORY
143 DRM_MEM_ERROR(area, "Attempt to free address 0\n");
144#endif
145 } else {
146 /* XXX - Is virt_to_page() legal for consistent mem? */
147 /* Unreserve */
148 for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
149 sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
150 ClearPageReserved(virt_to_page(addr));
151 }
152 dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
153 dmah->busaddr);
154 }
155
156#ifdef DRM_DEBUG_MEMORY
157 spin_lock(&drm_mem_lock);
158 free_count = ++drm_mem_stats[area].free_count;
159 alloc_count = drm_mem_stats[area].succeed_count;
160 drm_mem_stats[area].bytes_freed += size;
161 drm_ram_used -= size;
162 spin_unlock(&drm_mem_lock);
163 if (free_count > alloc_count) {
164 DRM_MEM_ERROR(area,
165 "Excess frees: %d frees, %d allocs\n",
166 free_count, alloc_count);
167 }
168#endif
169
170}
171
172/**
173 * \brief Free a PCI consistent memory block
174 */
175void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
176{
177 __drm_pci_free(dev, dmah);
178 kfree(dmah);
179}
180
181EXPORT_SYMBOL(drm_pci_free);
182
183/*@}*/