__NO_VERSION__ hasn't been needed since 2.3 days ditch it...
[platform/upstream/libdrm.git] / linux-core / drm_pci.c
1 /* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
2 /**
3  * \file drm_pci.h
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 Add support to map these buffers.
10  * \todo The wrappers here are so thin that they would be better off inlined..
11  *
12  * \author José Fonseca <jrfonseca@tungstengraphics.com>
13  * \author Leif Delgass <ldelgass@retinalburn.net>
14  */
15
16 /*
17  * Copyright 2003 José Fonseca.
18  * Copyright 2003 Leif Delgass.
19  * All Rights Reserved.
20  *
21  * Permission is hereby granted, free of charge, to any person obtaining a
22  * copy of this software and associated documentation files (the "Software"),
23  * to deal in the Software without restriction, including without limitation
24  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
25  * and/or sell copies of the Software, and to permit persons to whom the
26  * Software is furnished to do so, subject to the following conditions:
27  *
28  * The above copyright notice and this permission notice (including the next
29  * paragraph) shall be included in all copies or substantial portions of the
30  * Software.
31  *
32  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
35  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
36  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39
40
41 #include <linux/pci.h>
42 #include "drmP.h"
43
44 /**********************************************************************/
45 /** \name PCI memory */
46 /*@{*/
47
48
49 /**
50  * \brief Allocate a PCI consistent memory block, for DMA.
51  */
52 void *
53 DRM(pci_alloc)(drm_device_t *dev, size_t size, size_t align, 
54                dma_addr_t maxaddr, dma_addr_t *busaddr)
55 {
56         void *address;
57 #if 0
58         unsigned long addr;
59         size_t sz;
60 #endif
61 #if DRM_DEBUG_MEMORY
62         int area = DRM_MEM_DMA;
63
64         spin_lock(&DRM(mem_lock));
65         if ((DRM(ram_used) >> PAGE_SHIFT)
66             > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
67                 spin_unlock(&DRM(mem_lock));
68                 return 0;
69         }
70         spin_unlock(&DRM(mem_lock));
71 #endif
72
73         /* pci_alloc_consistent only guarantees alignment to the smallest 
74          * PAGE_SIZE order which is greater than or equal to the requested size.
75          * Return NULL here for now to make sure nobody tries for larger alignment
76          */
77         if (align > size)
78                 return NULL;
79
80         if (pci_set_dma_mask( dev->pdev, maxaddr ) != 0) {
81                 DRM_ERROR( "Setting pci dma mask failed\n" );
82                 return NULL;
83         }
84
85         address = pci_alloc_consistent( dev->pdev, size, busaddr );
86
87 #if DRM_DEBUG_MEMORY
88         if (address == NULL) {
89                 spin_lock(&DRM(mem_lock));
90                 ++DRM(mem_stats)[area].fail_count;
91                 spin_unlock(&DRM(mem_lock));
92                 return NULL;
93         }
94
95         spin_lock(&DRM(mem_lock));
96         ++DRM(mem_stats)[area].succeed_count;
97         DRM(mem_stats)[area].bytes_allocated += size;
98         DRM(ram_used)                        += size;
99         spin_unlock(&DRM(mem_lock));
100 #else
101         if (address == NULL)
102                 return NULL;
103 #endif
104
105         memset(address, 0, size);
106
107 #if 0
108         /* XXX - Is virt_to_page() legal for consistent mem? */
109                                 /* Reserve */
110         for (addr = (unsigned long)address, sz = size;
111              sz > 0;
112              addr += PAGE_SIZE, sz -= PAGE_SIZE) {
113                 SetPageReserved(virt_to_page(addr));
114         }
115 #endif
116
117         return address;
118 }
119
120 /**
121  * \brief Free a PCI consistent memory block.
122  */
123 void
124 DRM(pci_free)(drm_device_t *dev, size_t size, void *vaddr, dma_addr_t busaddr)
125 {
126 #if 0
127         unsigned long addr;
128         size_t sz;
129 #endif
130 #if DRM_DEBUG_MEMORY
131         int area = DRM_MEM_DMA;
132         int alloc_count;
133         int free_count;
134 #endif
135
136         if (!vaddr) {
137 #if DRM_DEBUG_MEMORY
138                 DRM_MEM_ERROR(area, "Attempt to free address 0\n");
139 #endif
140         } else {
141 #if 0
142                 /* XXX - Is virt_to_page() legal for consistent mem? */
143                                 /* Unreserve */
144                 for (addr = (unsigned long)vaddr, sz = size;
145                      sz > 0;
146                      addr += PAGE_SIZE, sz -= PAGE_SIZE) {
147                         ClearPageReserved(virt_to_page(addr));
148                 }
149 #endif
150                 pci_free_consistent( dev->pdev, size, vaddr, busaddr );
151         }
152
153 #if DRM_DEBUG_MEMORY
154         spin_lock(&DRM(mem_lock));
155         free_count  = ++DRM(mem_stats)[area].free_count;
156         alloc_count =   DRM(mem_stats)[area].succeed_count;
157         DRM(mem_stats)[area].bytes_freed += size;
158         DRM(ram_used)                    -= size;
159         spin_unlock(&DRM(mem_lock));
160         if (free_count > alloc_count) {
161                 DRM_MEM_ERROR(area,
162                               "Excess frees: %d frees, %d allocs\n",
163                               free_count, alloc_count);
164         }
165 #endif
166
167 }
168
169 /*@}*/