Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / drivers / staging / meilhaus / meslist.c
1 /**
2  * @file me_slist.c
3  *
4  * @brief Implements the subdevice list class.
5  * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  */
8
9 /*
10  * Copyright (C) 2007 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 "meerror.h"
28 #include "medefines.h"
29
30 #include "meslist.h"
31 #include "medebug.h"
32
33 int me_slist_query_number_subdevices(struct me_slist *slist, int *number)
34 {
35         PDEBUG_LOCKS("called.\n");
36         *number = slist->n;
37         return ME_ERRNO_SUCCESS;
38 }
39
40 unsigned int me_slist_get_number_subdevices(struct me_slist *slist)
41 {
42         PDEBUG_LOCKS("called.\n");
43         return slist->n;
44 }
45
46 me_subdevice_t *me_slist_get_subdevice(struct me_slist * slist,
47                                        unsigned int index)
48 {
49
50         struct list_head *pos;
51         me_subdevice_t *subdevice = NULL;
52         unsigned int i = 0;
53
54         PDEBUG_LOCKS("called.\n");
55
56         if (index >= slist->n) {
57                 PERROR("Index out of range.\n");
58                 return NULL;
59         }
60
61         list_for_each(pos, &slist->head) {
62                 if (i == index) {
63                         subdevice = list_entry(pos, me_subdevice_t, list);
64                         break;
65                 }
66
67                 ++i;
68         }
69
70         return subdevice;
71 }
72
73 int me_slist_get_subdevice_by_type(struct me_slist *slist,
74                                    unsigned int start_subdevice,
75                                    int type, int subtype, int *subdevice)
76 {
77         me_subdevice_t *pos;
78         int s_type, s_subtype;
79         unsigned int index = 0;
80
81         PDEBUG_LOCKS("called.\n");
82
83         if (start_subdevice >= slist->n) {
84                 PERROR("Start index out of range.\n");
85                 return ME_ERRNO_NOMORE_SUBDEVICE_TYPE;
86         }
87
88         list_for_each_entry(pos, &slist->head, list) {
89                 if (index < start_subdevice) {  // Go forward to start subdevice.
90                         ++index;
91                         continue;
92                 }
93
94                 pos->me_subdevice_query_subdevice_type(pos,
95                                                        &s_type, &s_subtype);
96
97                 if (subtype == ME_SUBTYPE_ANY) {
98                         if (s_type == type)
99                                 break;
100                 } else {
101                         if ((s_type == type) && (s_subtype == subtype))
102                                 break;
103                 }
104
105                 ++index;
106         }
107
108         if (index >= slist->n) {
109                 return ME_ERRNO_NOMORE_SUBDEVICE_TYPE;
110         }
111
112         *subdevice = index;
113
114         return ME_ERRNO_SUCCESS;
115 }
116
117 void me_slist_add_subdevice_tail(struct me_slist *slist,
118                                  me_subdevice_t * subdevice)
119 {
120         PDEBUG_LOCKS("called.\n");
121
122         list_add_tail(&subdevice->list, &slist->head);
123         ++slist->n;
124 }
125
126 me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist)
127 {
128
129         struct list_head *last;
130         me_subdevice_t *subdevice;
131
132         PDEBUG_LOCKS("called.\n");
133
134         if (list_empty(&slist->head))
135                 return NULL;
136
137         last = slist->head.prev;
138
139         subdevice = list_entry(last, me_subdevice_t, list);
140
141         list_del(last);
142
143         --slist->n;
144
145         return subdevice;
146 }
147
148 int me_slist_init(me_slist_t * slist)
149 {
150         PDEBUG_LOCKS("called.\n");
151
152         INIT_LIST_HEAD(&slist->head);
153         slist->n = 0;
154         return 0;
155 }
156
157 void me_slist_deinit(me_slist_t * slist)
158 {
159
160         struct list_head *s;
161         me_subdevice_t *subdevice;
162
163         PDEBUG_LOCKS("called.\n");
164
165         while (!list_empty(&slist->head)) {
166                 s = slist->head.next;
167                 list_del(s);
168                 subdevice = list_entry(s, me_subdevice_t, list);
169                 subdevice->me_subdevice_destructor(subdevice);
170         }
171
172         slist->n = 0;
173 }