diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-11 22:42:51 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-11 22:42:51 -0400 |
commit | c1d1979c99ca397241da4e3d7e0cb77f7ec28240 (patch) | |
tree | 2a988aae1ae7c08891543e844171cbcb4281a5bb /litmus/nvidia_info.c | |
parent | fd3aa01f176cf12b1625f4f46ba01f3340bb57ed (diff) | |
parent | 55e04c94b925b0790c2ae0a79f16e939e9bb2846 (diff) |
Merge branch 'wip-gpu-rtas12' into wip-slave-threads
Conflicts:
include/litmus/unistd_32.h
include/litmus/unistd_64.h
litmus/litmus.c
Diffstat (limited to 'litmus/nvidia_info.c')
-rw-r--r-- | litmus/nvidia_info.c | 597 |
1 files changed, 597 insertions, 0 deletions
diff --git a/litmus/nvidia_info.c b/litmus/nvidia_info.c new file mode 100644 index 000000000000..4b86a50d3bd1 --- /dev/null +++ b/litmus/nvidia_info.c | |||
@@ -0,0 +1,597 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/semaphore.h> | ||
3 | #include <linux/pci.h> | ||
4 | |||
5 | #include <litmus/sched_trace.h> | ||
6 | #include <litmus/nvidia_info.h> | ||
7 | #include <litmus/litmus.h> | ||
8 | |||
9 | #include <litmus/sched_plugin.h> | ||
10 | |||
11 | #include <litmus/binheap.h> | ||
12 | |||
13 | typedef unsigned char NvV8; /* "void": enumerated or multiple fields */ | ||
14 | typedef unsigned short NvV16; /* "void": enumerated or multiple fields */ | ||
15 | typedef unsigned char NvU8; /* 0 to 255 */ | ||
16 | typedef unsigned short NvU16; /* 0 to 65535 */ | ||
17 | typedef signed char NvS8; /* -128 to 127 */ | ||
18 | typedef signed short NvS16; /* -32768 to 32767 */ | ||
19 | typedef float NvF32; /* IEEE Single Precision (S1E8M23) */ | ||
20 | typedef double NvF64; /* IEEE Double Precision (S1E11M52) */ | ||
21 | typedef unsigned int NvV32; /* "void": enumerated or multiple fields */ | ||
22 | typedef unsigned int NvU32; /* 0 to 4294967295 */ | ||
23 | typedef unsigned long long NvU64; /* 0 to 18446744073709551615 */ | ||
24 | typedef union | ||
25 | { | ||
26 | volatile NvV8 Reg008[1]; | ||
27 | volatile NvV16 Reg016[1]; | ||
28 | volatile NvV32 Reg032[1]; | ||
29 | } litmus_nv_hwreg_t, * litmus_nv_phwreg_t; | ||
30 | |||
31 | typedef struct | ||
32 | { | ||
33 | NvU64 address; | ||
34 | NvU64 size; | ||
35 | NvU32 offset; | ||
36 | NvU32 *map; | ||
37 | litmus_nv_phwreg_t map_u; | ||
38 | } litmus_nv_aperture_t; | ||
39 | |||
40 | typedef struct | ||
41 | { | ||
42 | void *priv; /* private data */ | ||
43 | void *os_state; /* os-specific device state */ | ||
44 | |||
45 | int rmInitialized; | ||
46 | int flags; | ||
47 | |||
48 | /* PCI config info */ | ||
49 | NvU32 domain; | ||
50 | NvU16 bus; | ||
51 | NvU16 slot; | ||
52 | NvU16 vendor_id; | ||
53 | NvU16 device_id; | ||
54 | NvU16 subsystem_id; | ||
55 | NvU32 gpu_id; | ||
56 | void *handle; | ||
57 | |||
58 | NvU32 pci_cfg_space[16]; | ||
59 | |||
60 | /* physical characteristics */ | ||
61 | litmus_nv_aperture_t bars[3]; | ||
62 | litmus_nv_aperture_t *regs; | ||
63 | litmus_nv_aperture_t *fb, ud; | ||
64 | litmus_nv_aperture_t agp; | ||
65 | |||
66 | NvU32 interrupt_line; | ||
67 | |||
68 | NvU32 agp_config; | ||
69 | NvU32 agp_status; | ||
70 | |||
71 | NvU32 primary_vga; | ||
72 | |||
73 | NvU32 sim_env; | ||
74 | |||
75 | NvU32 rc_timer_enabled; | ||
76 | |||
77 | /* list of events allocated for this device */ | ||
78 | void *event_list; | ||
79 | |||
80 | void *kern_mappings; | ||
81 | |||
82 | } litmus_nv_state_t; | ||
83 | |||
84 | typedef struct work_struct litmus_nv_task_t; | ||
85 | |||
86 | typedef struct litmus_nv_work_s { | ||
87 | litmus_nv_task_t task; | ||
88 | void *data; | ||
89 | } litmus_nv_work_t; | ||
90 | |||
91 | typedef struct litmus_nv_linux_state_s { | ||
92 | litmus_nv_state_t nv_state; | ||
93 | atomic_t usage_count; | ||
94 | |||
95 | struct pci_dev *dev; | ||
96 | void *agp_bridge; | ||
97 | void *alloc_queue; | ||
98 | |||
99 | void *timer_sp; | ||
100 | void *isr_sp; | ||
101 | void *pci_cfgchk_sp; | ||
102 | void *isr_bh_sp; | ||
103 | |||
104 | #ifdef CONFIG_CUDA_4_0 | ||
105 | char registry_keys[512]; | ||
106 | #endif | ||
107 | |||
108 | /* keep track of any pending bottom halfes */ | ||
109 | struct tasklet_struct tasklet; | ||
110 | litmus_nv_work_t work; | ||
111 | |||
112 | /* get a timer callback every second */ | ||
113 | struct timer_list rc_timer; | ||
114 | |||
115 | /* lock for linux-specific data, not used by core rm */ | ||
116 | struct semaphore ldata_lock; | ||
117 | |||
118 | /* lock for linux-specific alloc queue */ | ||
119 | struct semaphore at_lock; | ||
120 | |||
121 | #if 0 | ||
122 | #if defined(NV_USER_MAP) | ||
123 | /* list of user mappings */ | ||
124 | struct nv_usermap_s *usermap_list; | ||
125 | |||
126 | /* lock for VMware-specific mapping list */ | ||
127 | struct semaphore mt_lock; | ||
128 | #endif /* defined(NV_USER_MAP) */ | ||
129 | #if defined(NV_PM_SUPPORT_OLD_STYLE_APM) | ||
130 | void *apm_nv_dev; | ||
131 | #endif | ||
132 | #endif | ||
133 | |||
134 | NvU32 device_num; | ||
135 | struct litmus_nv_linux_state_s *next; | ||
136 | } litmus_nv_linux_state_t; | ||
137 | |||
138 | void dump_nvidia_info(const struct tasklet_struct *t) | ||
139 | { | ||
140 | litmus_nv_state_t* nvstate = NULL; | ||
141 | litmus_nv_linux_state_t* linuxstate = NULL; | ||
142 | struct pci_dev* pci = NULL; | ||
143 | |||
144 | nvstate = (litmus_nv_state_t*)(t->data); | ||
145 | |||
146 | if(nvstate) | ||
147 | { | ||
148 | TRACE("NV State:\n" | ||
149 | "\ttasklet ptr = %p\n" | ||
150 | "\tstate ptr = %p\n" | ||
151 | "\tprivate data ptr = %p\n" | ||
152 | "\tos state ptr = %p\n" | ||
153 | "\tdomain = %u\n" | ||
154 | "\tbus = %u\n" | ||
155 | "\tslot = %u\n" | ||
156 | "\tvender_id = %u\n" | ||
157 | "\tdevice_id = %u\n" | ||
158 | "\tsubsystem_id = %u\n" | ||
159 | "\tgpu_id = %u\n" | ||
160 | "\tinterrupt_line = %u\n", | ||
161 | t, | ||
162 | nvstate, | ||
163 | nvstate->priv, | ||
164 | nvstate->os_state, | ||
165 | nvstate->domain, | ||
166 | nvstate->bus, | ||
167 | nvstate->slot, | ||
168 | nvstate->vendor_id, | ||
169 | nvstate->device_id, | ||
170 | nvstate->subsystem_id, | ||
171 | nvstate->gpu_id, | ||
172 | nvstate->interrupt_line); | ||
173 | |||
174 | linuxstate = container_of(nvstate, litmus_nv_linux_state_t, nv_state); | ||
175 | } | ||
176 | else | ||
177 | { | ||
178 | TRACE("INVALID NVSTATE????\n"); | ||
179 | } | ||
180 | |||
181 | if(linuxstate) | ||
182 | { | ||
183 | int ls_offset = (void*)(&(linuxstate->device_num)) - (void*)(linuxstate); | ||
184 | int ns_offset_raw = (void*)(&(linuxstate->device_num)) - (void*)(&(linuxstate->nv_state)); | ||
185 | int ns_offset_desired = (void*)(&(linuxstate->device_num)) - (void*)(nvstate); | ||
186 | |||
187 | |||
188 | TRACE("LINUX NV State:\n" | ||
189 | "\tlinux nv state ptr: %p\n" | ||
190 | "\taddress of tasklet: %p\n" | ||
191 | "\taddress of work: %p\n" | ||
192 | "\tusage_count: %d\n" | ||
193 | "\tdevice_num: %u\n" | ||
194 | "\ttasklet addr == this tasklet: %d\n" | ||
195 | "\tpci: %p\n", | ||
196 | linuxstate, | ||
197 | &(linuxstate->tasklet), | ||
198 | &(linuxstate->work), | ||
199 | atomic_read(&(linuxstate->usage_count)), | ||
200 | linuxstate->device_num, | ||
201 | (t == &(linuxstate->tasklet)), | ||
202 | linuxstate->dev); | ||
203 | |||
204 | pci = linuxstate->dev; | ||
205 | |||
206 | TRACE("Offsets:\n" | ||
207 | "\tOffset from LinuxState: %d, %x\n" | ||
208 | "\tOffset from NVState: %d, %x\n" | ||
209 | "\tOffset from parameter: %d, %x\n" | ||
210 | "\tdevice_num: %u\n", | ||
211 | ls_offset, ls_offset, | ||
212 | ns_offset_raw, ns_offset_raw, | ||
213 | ns_offset_desired, ns_offset_desired, | ||
214 | *((u32*)((void*)nvstate + ns_offset_desired))); | ||
215 | } | ||
216 | else | ||
217 | { | ||
218 | TRACE("INVALID LINUXNVSTATE?????\n"); | ||
219 | } | ||
220 | |||
221 | #if 0 | ||
222 | if(pci) | ||
223 | { | ||
224 | TRACE("PCI DEV Info:\n" | ||
225 | "pci device ptr: %p\n" | ||
226 | "\tdevfn = %d\n" | ||
227 | "\tvendor = %d\n" | ||
228 | "\tdevice = %d\n" | ||
229 | "\tsubsystem_vendor = %d\n" | ||
230 | "\tsubsystem_device = %d\n" | ||
231 | "\tslot # = %d\n", | ||
232 | pci, | ||
233 | pci->devfn, | ||
234 | pci->vendor, | ||
235 | pci->device, | ||
236 | pci->subsystem_vendor, | ||
237 | pci->subsystem_device, | ||
238 | pci->slot->number); | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | TRACE("INVALID PCIDEV PTR?????\n"); | ||
243 | } | ||
244 | #endif | ||
245 | } | ||
246 | |||
247 | static struct module* nvidia_mod = NULL; | ||
248 | int init_nvidia_info(void) | ||
249 | { | ||
250 | mutex_lock(&module_mutex); | ||
251 | nvidia_mod = find_module("nvidia"); | ||
252 | mutex_unlock(&module_mutex); | ||
253 | if(nvidia_mod != NULL) | ||
254 | { | ||
255 | TRACE("%s : Found NVIDIA module. Core Code: %p to %p\n", __FUNCTION__, | ||
256 | (void*)(nvidia_mod->module_core), | ||
257 | (void*)(nvidia_mod->module_core) + nvidia_mod->core_size); | ||
258 | init_nv_device_reg(); | ||
259 | return(0); | ||
260 | } | ||
261 | else | ||
262 | { | ||
263 | TRACE("%s : Could not find NVIDIA module! Loaded?\n", __FUNCTION__); | ||
264 | return(-1); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | void shutdown_nvidia_info(void) | ||
269 | { | ||
270 | nvidia_mod = NULL; | ||
271 | mb(); | ||
272 | } | ||
273 | |||
274 | /* works with pointers to static data inside the module too. */ | ||
275 | int is_nvidia_func(void* func_addr) | ||
276 | { | ||
277 | int ret = 0; | ||
278 | if(nvidia_mod) | ||
279 | { | ||
280 | ret = within_module_core((long unsigned int)func_addr, nvidia_mod); | ||
281 | /* | ||
282 | if(ret) | ||
283 | { | ||
284 | TRACE("%s : %p is in NVIDIA module: %d\n", | ||
285 | __FUNCTION__, func_addr, ret); | ||
286 | }*/ | ||
287 | } | ||
288 | |||
289 | return(ret); | ||
290 | } | ||
291 | |||
292 | u32 get_tasklet_nv_device_num(const struct tasklet_struct *t) | ||
293 | { | ||
294 | // life is too short to use hard-coded offsets. update this later. | ||
295 | litmus_nv_state_t* nvstate = (litmus_nv_state_t*)(t->data); | ||
296 | litmus_nv_linux_state_t* linuxstate = container_of(nvstate, litmus_nv_linux_state_t, nv_state); | ||
297 | |||
298 | BUG_ON(linuxstate->device_num >= NV_DEVICE_NUM); | ||
299 | |||
300 | return(linuxstate->device_num); | ||
301 | |||
302 | //int DEVICE_NUM_OFFSET = (void*)(&(linuxstate->device_num)) - (void*)(nvstate); | ||
303 | |||
304 | #if 0 | ||
305 | // offset determined though observed behavior of the NV driver. | ||
306 | //const int DEVICE_NUM_OFFSET = 0x480; // CUDA 4.0 RC1 | ||
307 | //const int DEVICE_NUM_OFFSET = 0x510; // CUDA 4.0 RC2 | ||
308 | |||
309 | void* state = (void*)(t->data); | ||
310 | void* device_num_ptr = state + DEVICE_NUM_OFFSET; | ||
311 | |||
312 | //dump_nvidia_info(t); | ||
313 | return(*((u32*)device_num_ptr)); | ||
314 | #endif | ||
315 | } | ||
316 | |||
317 | u32 get_work_nv_device_num(const struct work_struct *t) | ||
318 | { | ||
319 | // offset determined though observed behavior of the NV driver. | ||
320 | const int DEVICE_NUM_OFFSET = sizeof(struct work_struct); | ||
321 | void* state = (void*)(t); | ||
322 | void** device_num_ptr = state + DEVICE_NUM_OFFSET; | ||
323 | return(*((u32*)(*device_num_ptr))); | ||
324 | } | ||
325 | |||
326 | |||
327 | typedef struct { | ||
328 | raw_spinlock_t lock; | ||
329 | int nr_owners; | ||
330 | struct task_struct* max_prio_owner; | ||
331 | struct task_struct* owners[NV_MAX_SIMULT_USERS]; | ||
332 | }nv_device_registry_t; | ||
333 | |||
334 | static nv_device_registry_t NV_DEVICE_REG[NV_DEVICE_NUM]; | ||
335 | |||
336 | int init_nv_device_reg(void) | ||
337 | { | ||
338 | int i; | ||
339 | |||
340 | memset(NV_DEVICE_REG, 0, sizeof(NV_DEVICE_REG)); | ||
341 | |||
342 | for(i = 0; i < NV_DEVICE_NUM; ++i) | ||
343 | { | ||
344 | raw_spin_lock_init(&NV_DEVICE_REG[i].lock); | ||
345 | } | ||
346 | |||
347 | return(1); | ||
348 | } | ||
349 | |||
350 | /* use to get nv_device_id by given owner. | ||
351 | (if return -1, can't get the assocaite device id)*/ | ||
352 | /* | ||
353 | int get_nv_device_id(struct task_struct* owner) | ||
354 | { | ||
355 | int i; | ||
356 | if(!owner) | ||
357 | { | ||
358 | return(-1); | ||
359 | } | ||
360 | for(i = 0; i < NV_DEVICE_NUM; ++i) | ||
361 | { | ||
362 | if(NV_DEVICE_REG[i].device_owner == owner) | ||
363 | return(i); | ||
364 | } | ||
365 | return(-1); | ||
366 | } | ||
367 | */ | ||
368 | |||
369 | static struct task_struct* find_hp_owner(nv_device_registry_t *reg, struct task_struct *skip) { | ||
370 | int i; | ||
371 | struct task_struct *found = NULL; | ||
372 | for(i = 0; i < reg->nr_owners; ++i) { | ||
373 | if(reg->owners[i] && reg->owners[i] != skip && litmus->compare(reg->owners[i], found)) { | ||
374 | found = reg->owners[i]; | ||
375 | } | ||
376 | } | ||
377 | return found; | ||
378 | } | ||
379 | |||
380 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
381 | void pai_check_priority_increase(struct task_struct *t, int reg_device_id) | ||
382 | { | ||
383 | unsigned long flags; | ||
384 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; | ||
385 | |||
386 | if(reg->max_prio_owner != t) { | ||
387 | |||
388 | raw_spin_lock_irqsave(®->lock, flags); | ||
389 | |||
390 | if(reg->max_prio_owner != t) { | ||
391 | if(litmus->compare(t, reg->max_prio_owner)) { | ||
392 | litmus->change_prio_pai_tasklet(reg->max_prio_owner, t); | ||
393 | reg->max_prio_owner = t; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | |||
402 | void pai_check_priority_decrease(struct task_struct *t, int reg_device_id) | ||
403 | { | ||
404 | unsigned long flags; | ||
405 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; | ||
406 | |||
407 | if(reg->max_prio_owner == t) { | ||
408 | |||
409 | raw_spin_lock_irqsave(®->lock, flags); | ||
410 | |||
411 | if(reg->max_prio_owner == t) { | ||
412 | reg->max_prio_owner = find_hp_owner(reg, NULL); | ||
413 | if(reg->max_prio_owner != t) { | ||
414 | litmus->change_prio_pai_tasklet(t, reg->max_prio_owner); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
419 | } | ||
420 | } | ||
421 | #endif | ||
422 | |||
423 | static int __reg_nv_device(int reg_device_id, struct task_struct *t) | ||
424 | { | ||
425 | int ret = 0; | ||
426 | int i; | ||
427 | struct task_struct *old_max = NULL; | ||
428 | unsigned long flags; | ||
429 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; | ||
430 | |||
431 | if(test_bit(reg_device_id, &tsk_rt(t)->held_gpus)) { | ||
432 | // TODO: check if taks is already registered. | ||
433 | return ret; // assume already registered. | ||
434 | } | ||
435 | |||
436 | |||
437 | raw_spin_lock_irqsave(®->lock, flags); | ||
438 | |||
439 | if(reg->nr_owners < NV_MAX_SIMULT_USERS) { | ||
440 | TRACE_TASK(t, "registers GPU %d\n", reg_device_id); | ||
441 | for(i = 0; i < NV_MAX_SIMULT_USERS; ++i) { | ||
442 | if(reg->owners[i] == NULL) { | ||
443 | reg->owners[i] = t; | ||
444 | |||
445 | //if(edf_higher_prio(t, reg->max_prio_owner)) { | ||
446 | if(litmus->compare(t, reg->max_prio_owner)) { | ||
447 | old_max = reg->max_prio_owner; | ||
448 | reg->max_prio_owner = t; | ||
449 | |||
450 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
451 | litmus->change_prio_pai_tasklet(old_max, t); | ||
452 | #endif | ||
453 | } | ||
454 | |||
455 | #ifdef CONFIG_LITMUS_SOFTIRQD | ||
456 | down_and_set_stat(t, HELD, &tsk_rt(t)->klitirqd_sem); | ||
457 | #endif | ||
458 | ++(reg->nr_owners); | ||
459 | |||
460 | break; | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | else | ||
465 | { | ||
466 | TRACE_CUR("%s: device %d is already in use!\n", __FUNCTION__, reg_device_id); | ||
467 | //ret = -EBUSY; | ||
468 | } | ||
469 | |||
470 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
471 | |||
472 | __set_bit(reg_device_id, &tsk_rt(t)->held_gpus); | ||
473 | |||
474 | return(ret); | ||
475 | } | ||
476 | |||
477 | static int __clear_reg_nv_device(int de_reg_device_id, struct task_struct *t) | ||
478 | { | ||
479 | int ret = 0; | ||
480 | int i; | ||
481 | unsigned long flags; | ||
482 | nv_device_registry_t *reg = &NV_DEVICE_REG[de_reg_device_id]; | ||
483 | |||
484 | #ifdef CONFIG_LITMUS_SOFTIRQD | ||
485 | struct task_struct* klitirqd_th = get_klitirqd(de_reg_device_id); | ||
486 | #endif | ||
487 | |||
488 | if(!test_bit(de_reg_device_id, &tsk_rt(t)->held_gpus)) { | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | raw_spin_lock_irqsave(®->lock, flags); | ||
493 | |||
494 | TRACE_TASK(t, "unregisters GPU %d\n", de_reg_device_id); | ||
495 | |||
496 | for(i = 0; i < NV_MAX_SIMULT_USERS; ++i) { | ||
497 | if(reg->owners[i] == t) { | ||
498 | #ifdef CONFIG_LITMUS_SOFTIRQD | ||
499 | flush_pending(klitirqd_th, t); | ||
500 | #endif | ||
501 | if(reg->max_prio_owner == t) { | ||
502 | reg->max_prio_owner = find_hp_owner(reg, t); | ||
503 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
504 | litmus->change_prio_pai_tasklet(t, reg->max_prio_owner); | ||
505 | #endif | ||
506 | } | ||
507 | |||
508 | #ifdef CONFIG_LITMUS_SOFTIRQD | ||
509 | up_and_set_stat(t, NOT_HELD, &tsk_rt(t)->klitirqd_sem); | ||
510 | #endif | ||
511 | |||
512 | reg->owners[i] = NULL; | ||
513 | --(reg->nr_owners); | ||
514 | |||
515 | break; | ||
516 | } | ||
517 | } | ||
518 | |||
519 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
520 | |||
521 | __clear_bit(de_reg_device_id, &tsk_rt(t)->held_gpus); | ||
522 | |||
523 | return(ret); | ||
524 | } | ||
525 | |||
526 | |||
527 | int reg_nv_device(int reg_device_id, int reg_action, struct task_struct *t) | ||
528 | { | ||
529 | int ret; | ||
530 | |||
531 | if((reg_device_id < NV_DEVICE_NUM) && (reg_device_id >= 0)) | ||
532 | { | ||
533 | if(reg_action) | ||
534 | ret = __reg_nv_device(reg_device_id, t); | ||
535 | else | ||
536 | ret = __clear_reg_nv_device(reg_device_id, t); | ||
537 | } | ||
538 | else | ||
539 | { | ||
540 | ret = -ENODEV; | ||
541 | } | ||
542 | |||
543 | return(ret); | ||
544 | } | ||
545 | |||
546 | /* use to get the owner of nv_device_id. */ | ||
547 | struct task_struct* get_nv_max_device_owner(u32 target_device_id) | ||
548 | { | ||
549 | struct task_struct *owner = NULL; | ||
550 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
551 | owner = NV_DEVICE_REG[target_device_id].max_prio_owner; | ||
552 | return(owner); | ||
553 | } | ||
554 | |||
555 | void lock_nv_registry(u32 target_device_id, unsigned long* flags) | ||
556 | { | ||
557 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
558 | |||
559 | if(in_interrupt()) | ||
560 | TRACE("Locking registry for %d.\n", target_device_id); | ||
561 | else | ||
562 | TRACE_CUR("Locking registry for %d.\n", target_device_id); | ||
563 | |||
564 | raw_spin_lock_irqsave(&NV_DEVICE_REG[target_device_id].lock, *flags); | ||
565 | } | ||
566 | |||
567 | void unlock_nv_registry(u32 target_device_id, unsigned long* flags) | ||
568 | { | ||
569 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
570 | |||
571 | if(in_interrupt()) | ||
572 | TRACE("Unlocking registry for %d.\n", target_device_id); | ||
573 | else | ||
574 | TRACE_CUR("Unlocking registry for %d.\n", target_device_id); | ||
575 | |||
576 | raw_spin_unlock_irqrestore(&NV_DEVICE_REG[target_device_id].lock, *flags); | ||
577 | } | ||
578 | |||
579 | |||
580 | //void increment_nv_int_count(u32 device) | ||
581 | //{ | ||
582 | // unsigned long flags; | ||
583 | // struct task_struct* owner; | ||
584 | // | ||
585 | // lock_nv_registry(device, &flags); | ||
586 | // | ||
587 | // owner = NV_DEVICE_REG[device].device_owner; | ||
588 | // if(owner) | ||
589 | // { | ||
590 | // atomic_inc(&tsk_rt(owner)->nv_int_count); | ||
591 | // } | ||
592 | // | ||
593 | // unlock_nv_registry(device, &flags); | ||
594 | //} | ||
595 | //EXPORT_SYMBOL(increment_nv_int_count); | ||
596 | |||
597 | |||