Merge git://git.infradead.org/iommu-2.6
[sfrench/cifs-2.6.git] / drivers / staging / meilhaus / meslock.c
1 /**
2  * @file meslock.c
3  *
4  * @brief Implements the subdevice lock class.
5  * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  */
8
9 /*
10  * Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
11  *
12  * This file is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #include <linux/spinlock.h>
28
29 #include "medefines.h"
30 #include "meerror.h"
31
32 #include "medebug.h"
33 #include "meslock.h"
34
35 int me_slock_enter(struct me_slock *slock, struct file *filep)
36 {
37         PDEBUG_LOCKS("executed.\n");
38
39         spin_lock(&slock->spin_lock);
40
41         if ((slock->filep) != NULL && (slock->filep != filep)) {
42                 PERROR("Subdevice is locked by another process.\n");
43                 spin_unlock(&slock->spin_lock);
44                 return ME_ERRNO_LOCKED;
45         }
46
47         slock->count++;
48
49         spin_unlock(&slock->spin_lock);
50
51         return ME_ERRNO_SUCCESS;
52 }
53
54 int me_slock_exit(struct me_slock *slock, struct file *filep)
55 {
56         PDEBUG_LOCKS("executed.\n");
57
58         spin_lock(&slock->spin_lock);
59         slock->count--;
60         spin_unlock(&slock->spin_lock);
61
62         return ME_ERRNO_SUCCESS;
63 }
64
65 int me_slock_lock(struct me_slock *slock, struct file *filep, int lock)
66 {
67         PDEBUG_LOCKS("executed.\n");
68
69         switch (lock) {
70
71         case ME_LOCK_RELEASE:
72                 spin_lock(&slock->spin_lock);
73
74                 if (slock->filep == filep)
75                         slock->filep = NULL;
76
77                 spin_unlock(&slock->spin_lock);
78
79                 break;
80
81         case ME_LOCK_SET:
82                 spin_lock(&slock->spin_lock);
83
84                 if (slock->count) {
85                         spin_unlock(&slock->spin_lock);
86                         PERROR("Subdevice is used by another process.\n");
87                         return ME_ERRNO_USED;
88                 } else if (slock->filep == NULL)
89                         slock->filep = filep;
90                 else if (slock->filep != filep) {
91                         spin_unlock(&slock->spin_lock);
92                         PERROR("Subdevice is locked by another process.\n");
93                         return ME_ERRNO_LOCKED;
94                 }
95
96                 spin_unlock(&slock->spin_lock);
97
98                 break;
99
100         case ME_LOCK_CHECK:
101                 spin_lock(&slock->spin_lock);
102
103                 if (slock->count) {
104                         spin_unlock(&slock->spin_lock);
105                         return ME_ERRNO_USED;
106                 } else if ((slock->filep != NULL) && (slock->filep != filep)) {
107                         spin_unlock(&slock->spin_lock);
108                         return ME_ERRNO_LOCKED;
109                 }
110
111                 spin_unlock(&slock->spin_lock);
112
113                 break;
114
115         default:
116                 break;
117         }
118
119         return ME_ERRNO_SUCCESS;
120 }
121
122 void me_slock_deinit(struct me_slock *slock)
123 {
124         PDEBUG_LOCKS("executed.\n");
125 }
126
127 int me_slock_init(me_slock_t *slock)
128 {
129         PDEBUG_LOCKS("executed.\n");
130
131         slock->filep = NULL;
132         slock->count = 0;
133         spin_lock_init(&slock->spin_lock);
134
135         return 0;
136 }