Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: arch/arm/mach-tegra/nv/nvrm_user.c

Issue 3256004: [ARM] tegra: add nvos/nvrm/nvmap drivers (Closed) Base URL: ssh://git@gitrw.chromium.org/kernel.git
Patch Set: remove ap15 headers Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « arch/arm/mach-tegra/nv/nvrm/dispatch/nvrm_xpc_dispatch.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * arch/arm/mach-tegra/nvrm_user.c
3 *
4 * User-land access to NvRm APIs
5 *
6 * Copyright (c) 2008-2010, NVIDIA Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 #include <linux/module.h>
24 #include <linux/proc_fs.h>
25 #include <linux/miscdevice.h>
26 #include <linux/uaccess.h>
27 #include <linux/cpumask.h>
28 #include <linux/sched.h>
29 #include <linux/cpu.h>
30 #include <linux/platform_device.h>
31 #include <linux/freezer.h>
32 #include <linux/suspend.h>
33 #include <linux/percpu.h>
34 #ifdef CONFIG_HAS_EARLYSUSPEND
35 #include <linux/earlysuspend.h>
36 #endif
37 #include <linux/smp.h>
38 #include <asm/smp_twd.h>
39 #include <asm/cpu.h>
40 #include "nvcommon.h"
41 #include "nvassert.h"
42 #include "nvos.h"
43 #include "nvrm_memmgr.h"
44 #include "nvrm_ioctls.h"
45 #include "mach/nvrm_linux.h"
46 #include "linux/nvos_ioctl.h"
47 #include "nvrm_power_private.h"
48 #include "nvreftrack.h"
49 #include "mach/timex.h"
50
51 pid_t s_nvrm_daemon_pid = 0;
52
53 NvError NvRm_Dispatch(void *InBuffer,
54 NvU32 InSize,
55 void *OutBuffer,
56 NvU32 OutSize,
57 NvDispatchCtx* Ctx);
58
59 static int nvrm_open(struct inode *inode, struct file *file);
60 static int nvrm_close(struct inode *inode, struct file *file);
61 static long nvrm_unlocked_ioctl(struct file *file,
62 unsigned int cmd, unsigned long arg);
63 static int nvrm_mmap(struct file *file, struct vm_area_struct *vma);
64 extern void reset_cpu(unsigned int cpu, unsigned int reset);
65
66 static NvOsThreadHandle s_DfsThread = NULL;
67 static NvRtHandle s_RtHandle = NULL;
68
69 #define DEVICE_NAME "nvrm"
70
71 static const struct file_operations nvrm_fops =
72 {
73 .owner = THIS_MODULE,
74 .open = nvrm_open,
75 .release = nvrm_close,
76 .unlocked_ioctl = nvrm_unlocked_ioctl,
77 .mmap = nvrm_mmap
78 };
79
80 static struct miscdevice nvrm_dev =
81 {
82 .name = DEVICE_NAME,
83 .fops = &nvrm_fops,
84 .minor = MISC_DYNAMIC_MINOR,
85 };
86
87 #ifdef GHACK_DFS
88 static void NvRmDfsThread(void *args)
89 {
90 NvRmDeviceHandle hRm = (NvRmDeviceHandle)args;
91 struct cpumask cpu_mask;
92
93 //Ensure that only cpu0 is in the affinity mask
94 cpumask_clear(&cpu_mask);
95 cpumask_set_cpu(0, &cpu_mask);
96 if (sched_setaffinity(0, &cpu_mask))
97 {
98 panic("Unable to setaffinity of DFS thread!\n");
99 }
100
101 //Confirm that only CPU0 can run this thread
102 if (!cpumask_test_cpu(0, &cpu_mask) || cpumask_weight(&cpu_mask) != 1)
103 {
104 panic("Unable to setaffinity of DFS thread!\n");
105 }
106
107 set_freezable_with_signal();
108
109 if (NvRmDfsGetState(hRm) > NvRmDfsRunState_Disabled)
110 {
111 NvRmFreqKHz CpuKHz, f;
112 CpuKHz = NvRmPrivDfsGetCurrentKHz(NvRmDfsClockId_Cpu);
113 local_timer_rescale(CpuKHz);
114
115 NvRmDfsSetState(hRm, NvRmDfsRunState_ClosedLoop);
116
117 for (;;)
118 {
119 NvRmPmRequest Request = NvRmPrivPmThread();
120 f = NvRmPrivDfsGetCurrentKHz(NvRmDfsClockId_Cpu);
121 if (CpuKHz != f)
122 {
123 CpuKHz = f;
124 local_timer_rescale(CpuKHz);
125 twd_set_prescaler(NULL);
126 smp_call_function(twd_set_prescaler, NULL, NV_TRUE);
127 }
128 if (Request & NvRmPmRequest_ExitFlag)
129 {
130 break;
131 }
132 if (Request & NvRmPmRequest_CpuOnFlag)
133 {
134 #ifdef CONFIG_HOTPLUG_CPU
135 printk("DFS requested CPU1 ON\n");
136 preset_lpj = per_cpu(cpu_data, 0).loops_per_jiffy;
137 cpu_up(1);
138 smp_call_function(twd_set_prescaler, NULL, NV_TRUE);
139 #endif
140 }
141
142 if (Request & NvRmPmRequest_CpuOffFlag)
143 {
144 #ifdef CONFIG_HOTPLUG_CPU
145 printk("DFS requested CPU1 OFF\n");
146 cpu_down(1);
147 #endif
148 }
149 }
150 }
151 }
152 #endif
153
154 static void client_detach(NvRtClientHandle client)
155 {
156 if (NvRtUnregisterClient(s_RtHandle, client))
157 {
158 NvDispatchCtx dctx;
159
160 dctx.Rt = s_RtHandle;
161 dctx.Client = client;
162 dctx.PackageIdx = 0;
163
164 for (;;)
165 {
166 void* ptr = NvRtFreeObjRef(&dctx,
167 NvRtObjType_NvRm_NvRmMemHandle,
168 NULL);
169 if (!ptr) break;
170 NVRT_LEAK("NvRm", "NvRmMemHandle", ptr);
171 NvRmMemHandleFree(ptr);
172 }
173
174 NvRtUnregisterClient(s_RtHandle, client);
175 }
176 }
177
178 int nvrm_open(struct inode *inode, struct file *file)
179 {
180 NvRtClientHandle Client;
181
182 if (NvRtRegisterClient(s_RtHandle, &Client) != NvSuccess)
183 {
184 return -ENOMEM;
185 }
186
187 file->private_data = (void*)Client;
188
189 return 0;
190 }
191
192 int nvrm_close(struct inode *inode, struct file *file)
193 {
194 client_detach((NvRtClientHandle)file->private_data);
195 return 0;
196 }
197
198 long nvrm_unlocked_ioctl(struct file *file,
199 unsigned int cmd, unsigned long arg)
200 {
201 NvError err;
202 NvOsIoctlParams p;
203 NvU32 size;
204 NvU32 small_buf[8];
205 void *ptr = 0;
206 long e;
207 NvBool bAlloc = NV_FALSE;
208
209 switch( cmd ) {
210 case NvRmIoctls_Generic:
211 {
212 NvDispatchCtx dctx;
213
214 dctx.Rt = s_RtHandle;
215 dctx.Client = (NvRtClientHandle)file->private_data;
216 dctx.PackageIdx = 0;
217
218 err = NvOsCopyIn( &p, (void *)arg, sizeof(p) );
219 if( err != NvSuccess )
220 {
221 printk( "NvRmIoctls_Generic: copy in failed\n" );
222 goto fail;
223 }
224
225 //printk( "NvRmIoctls_Generic: %d %d %d\n", p.InBufferSize,
226 // p.InOutBufferSize, p.OutBufferSize );
227
228 size = p.InBufferSize + p.InOutBufferSize + p.OutBufferSize;
229 if( size <= sizeof(small_buf) )
230 {
231 ptr = small_buf;
232 }
233 else
234 {
235 ptr = NvOsAlloc( size );
236 if( !ptr )
237 {
238 printk( "NvRmIoctls_Generic: alloc failure (%d bytes)\n",
239 size );
240 goto fail;
241 }
242
243 bAlloc = NV_TRUE;
244 }
245
246 err = NvOsCopyIn( ptr, p.pBuffer, p.InBufferSize +
247 p.InOutBufferSize );
248 if( err != NvSuccess )
249 {
250 printk( "NvRmIoctls_Generic: copy in failure\n" );
251 goto fail;
252 }
253
254 err = NvRm_Dispatch( ptr, p.InBufferSize + p.InOutBufferSize,
255 ((NvU8 *)ptr) + p.InBufferSize, p.InOutBufferSize +
256 p.OutBufferSize, &dctx );
257 if( err != NvSuccess )
258 {
259 printk( "NvRmIoctls_Generic: dispatch failure\n" );
260 goto fail;
261 }
262
263 if( p.InOutBufferSize || p.OutBufferSize )
264 {
265 err = NvOsCopyOut( ((NvU8 *)((NvOsIoctlParams *)arg)->pBuffer)
266 + p.InBufferSize,
267 ((NvU8 *)ptr) + p.InBufferSize,
268 p.InOutBufferSize + p.OutBufferSize );
269 if( err != NvSuccess )
270 {
271 printk( "NvRmIoctls_Generic: copy out failure\n" );
272 goto fail;
273 }
274 }
275
276 break;
277 }
278 case NvRmIoctls_NvRmGraphics:
279 printk( "NvRmIoctls_NvRmGraphics: not supported\n" );
280 goto fail;
281 case NvRmIoctls_NvRmFbControl:
282 printk( "NvRmIoctls_NvRmFbControl: deprecated \n" );
283 break;
284
285 case NvRmIoctls_NvRmMemRead:
286 case NvRmIoctls_NvRmMemWrite:
287 case NvRmIoctls_NvRmMemReadStrided:
288 case NvRmIoctls_NvRmGetCarveoutInfo:
289 case NvRmIoctls_NvRmMemWriteStrided:
290 goto fail;
291
292 case NvRmIoctls_NvRmMemMapIntoCallerPtr:
293 // FIXME: implement?
294 printk( "NvRmIoctls_NvRmMemMapIntoCallerPtr: not supported\n" );
295 goto fail;
296 case NvRmIoctls_NvRmBootDone:
297 #ifdef GHACK_DFS
298 if (!s_DfsThread)
299 {
300 if (NvOsInterruptPriorityThreadCreate(NvRmDfsThread,
301 (void*)s_hRmGlobal, &s_DfsThread)!=NvSuccess)
302 {
303 NvOsDebugPrintf("Failed to create DFS processing thread\n");
304 goto fail;
305 }
306 }
307 #endif
308 break;
309 case NvRmIoctls_NvRmGetClientId:
310 err = NvOsCopyIn(&p, (void*)arg, sizeof(p));
311 if (err != NvSuccess)
312 {
313 NvOsDebugPrintf("NvRmIoctls_NvRmGetClientId: copy in fai led\n");
314 goto fail;
315 }
316
317 NV_ASSERT(p.InBufferSize == 0);
318 NV_ASSERT(p.OutBufferSize == sizeof(NvRtClientHandle));
319 NV_ASSERT(p.InOutBufferSize == 0);
320
321 if (NvOsCopyOut(p.pBuffer,
322 &file->private_data,
323 sizeof(NvRtClientHandle)) != NvS uccess)
324 {
325 NvOsDebugPrintf("Failed to copy client id\n");
326 goto fail;
327 }
328 break;
329 case NvRmIoctls_NvRmClientAttach:
330 {
331 NvRtClientHandle Client;
332
333 err = NvOsCopyIn(&p, (void*)arg, sizeof(p));
334 if (err != NvSuccess)
335 {
336 NvOsDebugPrintf("NvRmIoctls_NvRmClientAttach: copy in fa iled\n");
337 goto fail;
338 }
339
340 NV_ASSERT(p.InBufferSize == sizeof(NvRtClientHandle));
341 NV_ASSERT(p.OutBufferSize == 0);
342 NV_ASSERT(p.InOutBufferSize == 0);
343
344 if (NvOsCopyIn((void*)&Client,
345 p.pBuffer,
346 sizeof(NvRtClientHandle)) != NvSucces s)
347 {
348 NvOsDebugPrintf("Failed to copy client id\n");
349 goto fail;
350 }
351
352 NV_ASSERT(Client || !"Bad client");
353
354 if (Client == (NvRtClientHandle)file->private_data)
355 {
356 // The daemon is attaching to itself, no need to add ref count
357 break;
358 }
359 if (NvRtAddClientRef(s_RtHandle, Client) != NvSuccess)
360 {
361 NvOsDebugPrintf("Client ref add unsuccessful\n");
362 goto fail;
363 }
364 break;
365 }
366 case NvRmIoctls_NvRmClientDetach:
367 {
368 NvRtClientHandle Client;
369
370 err = NvOsCopyIn(&p, (void*)arg, sizeof(p));
371 if (err != NvSuccess)
372 {
373 NvOsDebugPrintf("NvRmIoctls_NvRmClientAttach: copy in fa iled\n");
374 goto fail;
375 }
376
377 NV_ASSERT(p.InBufferSize == sizeof(NvRtClientHandle));
378 NV_ASSERT(p.OutBufferSize == 0);
379 NV_ASSERT(p.InOutBufferSize == 0);
380
381 if (NvOsCopyIn((void*)&Client,
382 p.pBuffer,
383 sizeof(NvRtClientHandle)) != NvSucces s)
384 {
385 NvOsDebugPrintf("Failed to copy client id\n");
386 goto fail;
387 }
388
389 NV_ASSERT(Client || !"Bad client");
390
391 if (Client == (NvRtClientHandle)file->private_data)
392 {
393 // The daemon is detaching from itself, no need to dec r efcount
394 break;
395 }
396
397 client_detach(Client);
398 break;
399 }
400 // FIXME: power ioctls?
401 default:
402 printk( "unknown ioctl code\n" );
403 goto fail;
404 }
405
406 e = 0;
407 goto clean;
408
409 fail:
410 e = -EINVAL;
411
412 clean:
413 if( bAlloc )
414 {
415 NvOsFree( ptr );
416 }
417
418 return e;
419 }
420
421 int nvrm_mmap(struct file *file, struct vm_area_struct *vma)
422 {
423 return 0;
424 }
425
426 static int nvrm_probe(struct platform_device *pdev)
427 {
428 int e = 0;
429 NvU32 NumTypes = NvRtObjType_NvRm_Num;
430
431 printk("nvrm probe\n");
432
433 NV_ASSERT(s_RtHandle == NULL);
434
435 if (NvRtCreate(1, &NumTypes, &s_RtHandle) != NvSuccess)
436 {
437 e = -ENOMEM;
438 }
439
440 if (e == 0)
441 {
442 e = misc_register( &nvrm_dev );
443 }
444
445 if( e < 0 )
446 {
447 if (s_RtHandle)
448 {
449 NvRtDestroy(s_RtHandle);
450 s_RtHandle = NULL;
451 }
452
453 printk("nvrm probe failed to open\n");
454 }
455 return e;
456 }
457
458 static int nvrm_remove(struct platform_device *pdev)
459 {
460 misc_deregister( &nvrm_dev );
461 NvRtDestroy(s_RtHandle);
462 s_RtHandle = NULL;
463 return 0;
464 }
465
466 static int nvrm_suspend(struct platform_device *pdev, pm_message_t state)
467 {
468 #ifdef GHACK
469 if(NvRmKernelPowerSuspend(s_hRmGlobal)) {
470 printk(KERN_INFO "%s : FAILED\n", __func__);
471 return -1;
472 }
473 #endif
474 return 0;
475 }
476
477 static int nvrm_resume(struct platform_device *pdev)
478 {
479 #ifdef GHACK
480 if(NvRmKernelPowerResume(s_hRmGlobal)) {
481 printk(KERN_INFO "%s : FAILED\n", __func__);
482 return -1;
483 }
484 #endif
485 return 0;
486
487 }
488
489 static struct platform_driver nvrm_driver =
490 {
491 .probe = nvrm_probe,
492 .remove = nvrm_remove,
493 .suspend = nvrm_suspend,
494 .resume = nvrm_resume,
495 .driver = { .name = "nvrm" }
496 };
497
498 #if defined(CONFIG_PM)
499 //
500 // /sys/power/nvrm/notifier
501 //
502
503 wait_queue_head_t tegra_pm_notifier_wait;
504 wait_queue_head_t sys_nvrm_notifier_wait;
505
506 int tegra_pm_notifier_continue_ok;
507
508 struct kobject *nvrm_kobj;
509
510 const char* sys_nvrm_notifier;
511
512 static const char *STRING_PM_SUSPEND_PREPARE = "PM_SUSPEND_PREPARE";
513 static const char *STRING_PM_POST_SUSPEND = "PM_POST_SUSPEND";
514 static const char *STRING_PM_DISPLAY_OFF = "PM_DISPLAY_OFF";
515 static const char *STRING_PM_DISPLAY_ON = "PM_DISPLAY_ON";
516 static const char *STRING_PM_CONTINUE = "PM_CONTINUE";
517 static const char *STRING_PM_SIGNAL = "PM_SIGNAL";
518
519 // Reading blocks if the value is not available.
520 static ssize_t
521 nvrm_notifier_show(struct kobject *kobj, struct kobj_attribute *attr,
522 char *buf)
523 {
524 int nchar;
525
526 // Block if the value is not available yet.
527 if (! sys_nvrm_notifier)
528 {
529 printk(KERN_INFO "%s: blocking\n", __func__);
530 wait_event_interruptible(sys_nvrm_notifier_wait, sys_nvrm_notifier);
531 }
532
533 // In case of false wakeup, return "".
534 if (! sys_nvrm_notifier)
535 {
536 printk(KERN_INFO "%s: false wakeup, returning with '\\n'\n", __func_ _);
537 nchar = sprintf(buf, "\n");
538 return nchar;
539 }
540
541 // Return the value, and clear.
542 printk(KERN_INFO "%s: returning with '%s'\n", __func__, sys_nvrm_notifie r);
543 nchar = sprintf(buf, "%s\n", sys_nvrm_notifier);
544 sys_nvrm_notifier = NULL;
545 return nchar;
546 }
547
548 // Writing is no blocking.
549 static ssize_t
550 nvrm_notifier_store(struct kobject *kobj, struct kobj_attribute *attr,
551 const char *buf, size_t count)
552 {
553 if (!strncmp(buf, STRING_PM_CONTINUE, strlen(STRING_PM_CONTINUE))) {
554 // Wake up pm_notifier.
555 tegra_pm_notifier_continue_ok = 1;
556 wake_up(&tegra_pm_notifier_wait);
557 }
558 else if (!strncmp(buf, STRING_PM_SIGNAL, strlen(STRING_PM_SIGNAL))) {
559 s_nvrm_daemon_pid = 0;
560 sscanf(buf, "%*s %d", &s_nvrm_daemon_pid);
561 printk(KERN_INFO "%s: nvrm_daemon=%d\n", __func__, s_nvrm_daemon _pid);
562 }
563 else {
564 printk(KERN_ERR "%s: wrong value '%s'\n", __func__, buf);
565 }
566
567 return count;
568 }
569
570 static struct kobj_attribute nvrm_notifier_attribute =
571 __ATTR(notifier, 0666, nvrm_notifier_show, nvrm_notifier_store);
572
573 //
574 // PM notifier
575 //
576
577 static void notify_daemon(const char* notice)
578 {
579 long timeout = HZ * 30;
580
581 // In case daemon's pid is not reported, do not signal or wait.
582 if (!s_nvrm_daemon_pid) {
583 printk(KERN_ERR "%s: don't know nvrm_daemon's PID\n", __func__);
584 return;
585 }
586
587 // Clear before kicking nvrm_daemon.
588 tegra_pm_notifier_continue_ok = 0;
589
590 // Notify nvrm_daemon.
591 sys_nvrm_notifier = notice;
592 wake_up(&sys_nvrm_notifier_wait);
593
594 // Wait for the reply from nvrm_daemon.
595 printk(KERN_INFO "%s: wait for nvrm_daemon\n", __func__);
596 if (wait_event_timeout(tegra_pm_notifier_wait,
597 tegra_pm_notifier_continue_ok, timeout) == 0) {
598 printk(KERN_ERR "%s: timed out. nvrm_daemon did not reply\n", __func __);
599 }
600
601 // Go back to the initial state.
602 sys_nvrm_notifier = NULL;
603 }
604
605 int tegra_pm_notifier(struct notifier_block *nb,
606 unsigned long event, void *nouse)
607 {
608 printk(KERN_INFO "%s: start processing event=%lx\n", __func__, event);
609
610 // Notify the event to nvrm_daemon.
611 if (event == PM_SUSPEND_PREPARE) {
612 #ifndef CONFIG_HAS_EARLYSUSPEND
613 notify_daemon(STRING_PM_DISPLAY_OFF);
614 #endif
615 notify_daemon(STRING_PM_SUSPEND_PREPARE);
616 }
617 else if (event == PM_POST_SUSPEND) {
618 notify_daemon(STRING_PM_POST_SUSPEND);
619 #ifndef CONFIG_HAS_EARLYSUSPEND
620 notify_daemon(STRING_PM_DISPLAY_ON);
621 #endif
622 }
623 else {
624 printk(KERN_ERR "%s: unknown event %ld\n", __func__, event);
625 return NOTIFY_DONE;
626 }
627
628 printk(KERN_INFO "%s: finished processing event=%ld\n", __func__, event) ;
629 return NOTIFY_OK;
630 }
631
632 #ifdef CONFIG_HAS_EARLYSUSPEND
633 void tegra_display_off(struct early_suspend *h)
634 {
635 notify_daemon(STRING_PM_DISPLAY_OFF);
636 }
637
638 void tegra_display_on(struct early_suspend *h)
639 {
640 notify_daemon(STRING_PM_DISPLAY_ON);
641 }
642
643 static struct early_suspend tegra_display_power =
644 {
645 .suspend = tegra_display_off,
646 .resume = tegra_display_on,
647 .level = EARLY_SUSPEND_LEVEL_DISABLE_FB
648 };
649 #endif
650 #endif
651
652 static struct platform_device nvrm_device =
653 {
654 .name = "nvrm"
655 };
656
657
658 static int __init nvrm_init(void)
659 {
660 int ret = 0;
661 printk(KERN_INFO "%s called\n", __func__);
662
663 #if defined(CONFIG_PM)
664 // Register PM notifier.
665 pm_notifier(tegra_pm_notifier, 0);
666 tegra_pm_notifier_continue_ok = 0;
667 init_waitqueue_head(&tegra_pm_notifier_wait);
668
669 #if defined(CONFIG_HAS_EARLYSUSPEND)
670 register_early_suspend(&tegra_display_power);
671 #endif
672
673 // Create /sys/power/nvrm/notifier.
674 nvrm_kobj = kobject_create_and_add("nvrm", power_kobj);
675 sysfs_create_file(nvrm_kobj, &nvrm_notifier_attribute.attr);
676 sys_nvrm_notifier = NULL;
677 init_waitqueue_head(&sys_nvrm_notifier_wait);
678 #endif
679
680 // Register NvRm platform driver.
681 ret = platform_driver_register(&nvrm_driver);
682
683 platform_device_register(&nvrm_device);
684
685 return ret;
686 }
687
688 static void __exit nvrm_deinit(void)
689 {
690 printk(KERN_INFO "%s called\n", __func__);
691 platform_driver_unregister(&nvrm_driver);
692 }
693
694 module_init(nvrm_init);
695 module_exit(nvrm_deinit);
OLDNEW
« no previous file with comments | « arch/arm/mach-tegra/nv/nvrm/dispatch/nvrm_xpc_dispatch.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698