import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / ia64 / sn / io / drivers / hubdev.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/config.h>
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <asm/sn/sgi.h>
13 #include <asm/sn/io.h>
14 #include <asm/sn/iograph.h>
15 #include <asm/sn/sn_private.h>
16 #include <asm/sn/invent.h>
17 #include <asm/sn/hcl.h>
18 #include <asm/sn/labelcl.h>
19
20 struct hubdev_callout {
21         int (*attach_method)(vertex_hdl_t);
22         struct hubdev_callout *fp;
23 };
24
25 typedef struct hubdev_callout hubdev_callout_t;
26
27 mutex_t hubdev_callout_mutex;
28 static hubdev_callout_t *hubdev_callout_list;
29
30 void
31 hubdev_init(void)
32 {
33         mutex_init(&hubdev_callout_mutex);
34         hubdev_callout_list = NULL;
35 }
36         
37 void
38 hubdev_register(int (*attach_method)(vertex_hdl_t))
39 {
40         hubdev_callout_t *callout;
41         
42         ASSERT(attach_method);
43
44         callout =  (hubdev_callout_t *)snia_kmem_zalloc(sizeof(hubdev_callout_t), KM_SLEEP);
45         ASSERT(callout);
46         
47         mutex_lock(&hubdev_callout_mutex);
48         /*
49          * Insert at the end of the list
50          */
51         callout->fp = hubdev_callout_list;
52         hubdev_callout_list = callout;
53         callout->attach_method = attach_method;
54         mutex_unlock(&hubdev_callout_mutex);
55 }
56
57 int
58 hubdev_unregister(int (*attach_method)(vertex_hdl_t))
59 {
60         hubdev_callout_t **p;
61         
62         ASSERT(attach_method);
63    
64         mutex_lock(&hubdev_callout_mutex);
65         /*
66          * Remove registry element containing attach_method
67          */
68         for (p = &hubdev_callout_list; *p != NULL; p = &(*p)->fp) {
69                 if ((*p)->attach_method == attach_method) {
70                         hubdev_callout_t* victim = *p;
71                         *p = (*p)->fp;
72                         kfree(victim);
73                         mutex_unlock(&hubdev_callout_mutex);
74                         return (0);
75                 }
76         }
77         mutex_unlock(&hubdev_callout_mutex);
78         return (ENOENT);
79 }
80
81
82 int
83 hubdev_docallouts(vertex_hdl_t hub)
84 {
85         hubdev_callout_t *p;
86         int errcode;
87
88         mutex_lock(&hubdev_callout_mutex);
89         
90         for (p = hubdev_callout_list; p != NULL; p = p->fp) {
91                 ASSERT(p->attach_method);
92                 errcode = (*p->attach_method)(hub);
93                 if (errcode != 0) {
94                         mutex_unlock(&hubdev_callout_mutex);
95                         return (errcode);
96                 }
97         }
98         mutex_unlock(&hubdev_callout_mutex);
99         return (0);
100 }