gpu: pvr: optimize pvr_lock() by inlining it
[sgx.git] / pvr / module.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #include <linux/init.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/version.h>
31 #include <linux/fs.h>
32 #include <linux/proc_fs.h>
33 #include <linux/miscdevice.h>
34
35 #include <linux/platform_device.h>
36
37 #include "img_defs.h"
38 #include "services.h"
39 #include "kerneldisplay.h"
40 #include "kernelbuffer.h"
41 #include "syscommon.h"
42 #include "pvrmmap.h"
43 #include "mutils.h"
44 #include "mm.h"
45 #include "mmap.h"
46 #include "pvr_debug.h"
47 #include "srvkm.h"
48 #include "perproc.h"
49 #include "handle.h"
50 #include "pvr_bridge_km.h"
51 #include "sgx_bridge_km.h"
52 #include "proc.h"
53 #include "pvrmodule.h"
54 #include "private_data.h"
55 #include "pvr_events.h"
56
57 #define DRVNAME         "pvrsrvkm"
58
59 #ifdef CONFIG_PVR_DEBUG_EXTRA
60 static int debug = DBGPRIV_WARNING;
61 #include <linux/moduleparam.h>
62 module_param(debug, int, 0);
63 #endif
64
65 static int pvr_open(struct inode unref__ * inode, struct file *filp)
66 {
67         struct PVRSRV_FILE_PRIVATE_DATA *priv;
68         void *block_alloc;
69         int ret = -ENOMEM;
70         enum PVRSRV_ERROR err;
71         u32 pid;
72
73         pvr_lock();
74
75         pid = OSGetCurrentProcessIDKM();
76
77         if (PVRSRVProcessConnect(pid) != PVRSRV_OK)
78                 goto err_unlock;
79
80         err = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
81                             sizeof(*priv),
82                             (void **)&priv, &block_alloc);
83
84         if (err != PVRSRV_OK)
85                 goto err_unlock;
86
87         priv->ui32OpenPID = pid;
88         priv->hBlockAlloc = block_alloc;
89         filp->private_data = priv;
90
91         INIT_LIST_HEAD(&priv->event_list);
92         init_waitqueue_head(&priv->event_wait);
93         priv->event_space = 4096; /* set aside 4k for event buffer */
94
95         ret = 0;
96 err_unlock:
97         pvr_unlock();
98
99         return ret;
100 }
101
102 static int pvr_release(struct inode unref__ * inode, struct file *filp)
103 {
104         struct PVRSRV_FILE_PRIVATE_DATA *priv;
105
106         pvr_lock();
107
108         priv = filp->private_data;
109
110         pvr_release_events(priv);
111
112         PVRSRVProcessDisconnect(priv->ui32OpenPID);
113
114         OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
115                   sizeof(*priv),
116                   priv, priv->hBlockAlloc);
117
118         pvr_unlock();
119
120         return 0;
121 }
122
123 static const struct file_operations pvr_fops = {
124         .owner          = THIS_MODULE,
125         .unlocked_ioctl = PVRSRV_BridgeDispatchKM,
126         .open           = pvr_open,
127         .release        = pvr_release,
128         .mmap           = PVRMMap,
129         .poll           = pvr_poll,
130         .read           = pvr_read,
131 };
132
133 static void pvr_shutdown(struct platform_device *pdev)
134 {
135         PVR_TRACE("pvr_shutdown(pdev=%p)", pdev);
136
137         (void)PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3);
138 }
139
140 static int pvr_suspend(struct platform_device *pdev, pm_message_t state)
141 {
142         PVR_TRACE("pvr_suspend(pdev=%p)", pdev);
143
144         if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3) != PVRSRV_OK)
145                 return -EINVAL;
146         return 0;
147 }
148
149 static int pvr_resume(struct platform_device *pdev)
150 {
151         PVR_TRACE("pvr_resume(pdev=%p)", pdev);
152
153         if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D0) != PVRSRV_OK)
154                 return -EINVAL;
155         return 0;
156 }
157
158 static struct miscdevice pvr_miscdevice = {
159         .minor = MISC_DYNAMIC_MINOR,
160         .name = DRVNAME,
161         .fops = &pvr_fops,
162 };
163
164 static int __devinit pvr_probe(struct platform_device *pdev)
165 {
166         struct SYS_DATA *sysdata;
167         int ret;
168
169         PVR_TRACE("pvr_probe(pdev=%p)", pdev);
170
171         if (SysAcquireData(&sysdata) != PVRSRV_OK &&
172             SysInitialise(pdev) != PVRSRV_OK) {
173                 ret = -ENODEV;
174                 goto err_exit;
175         }
176
177         ret = misc_register(&pvr_miscdevice);
178         if (ret < 0)
179                 goto err_exit;
180
181         return 0;
182
183 err_exit:
184         dev_err(&pdev->dev, "probe failed (%d)\n", ret);
185
186         return ret;
187 }
188
189 static int __devexit pvr_remove(struct platform_device *pdev)
190 {
191         struct SYS_DATA *sysdata;
192         int ret;
193
194         PVR_TRACE("pvr_remove(pdev=%p)", pdev);
195
196         ret = misc_deregister(&pvr_miscdevice);
197         if (ret < 0) {
198                 dev_err(&pdev->dev, "remove failed (%d)\n", ret);
199                 return ret;
200         }
201
202         if (SysAcquireData(&sysdata) == PVRSRV_OK)
203                 SysDeinitialise(sysdata);
204
205         return 0;
206 }
207
208
209 static struct platform_driver pvr_driver = {
210         .driver = {
211                    .name = DRVNAME,
212         },
213         .probe          = pvr_probe,
214         .remove         = __devexit_p(pvr_remove),
215         .suspend        = pvr_suspend,
216         .resume         = pvr_resume,
217         .shutdown       = pvr_shutdown,
218 };
219
220 static int __init pvr_init(void)
221 {
222         int error;
223
224         pvr_dbg_init();
225
226         PVR_TRACE("pvr_init");
227
228 #ifdef CONFIG_PVR_DEBUG_EXTRA
229         PVRDebugSetLevel(debug);
230 #endif
231
232         error = CreateProcEntries();
233         if (error < 0)
234                 goto err1;
235
236         error = -ENOMEM;
237         if (LinuxMMInit() != PVRSRV_OK)
238                 goto err2;
239
240         if (LinuxBridgeInit() != PVRSRV_OK)
241                 goto err3;
242
243         PVRMMapInit();
244
245         error = platform_driver_register(&pvr_driver);
246         if (error < 0)
247                 goto err4;
248
249         pvr_init_events();
250
251         return 0;
252
253 err4:
254         PVRMMapCleanup();
255         LinuxBridgeDeInit();
256 err3:
257         LinuxMMCleanup();
258 err2:
259         RemoveProcEntries();
260 err1:
261         pr_err("%s: failed (%d)\n", __func__, error);
262
263         return error;
264 }
265
266 static void __exit pvr_cleanup(void)
267 {
268         struct SYS_DATA *sysdata;
269
270         PVR_TRACE("pvr_cleanup");
271
272         SysAcquireData(&sysdata);
273
274         platform_driver_unregister(&pvr_driver);
275
276         PVRMMapCleanup();
277         LinuxMMCleanup();
278         LinuxBridgeDeInit();
279         RemoveProcEntries();
280
281         PVR_TRACE("pvr_cleanup: unloading");
282
283         pvr_dbg_cleanup();
284 }
285
286 module_init(pvr_init);
287 module_exit(pvr_cleanup);
288
289 MODULE_SUPPORTED_DEVICE(DRVNAME);
290 MODULE_ALIAS("platform:" DRVNAME);
291