more changes on original files
[linux-2.4.git] / arch / ppc64 / kernel / iSeries_proc.c
1 /*
2   * iSeries_proc.c
3   * Copyright (C) 2001  Kyle A. Lucke IBM Corporation
4   * 
5   * This program is free software; you can redistribute it and/or modify
6   * it under the terms of the GNU General Public License as published by
7   * the Free Software Foundation; either version 2 of the License, or
8   * (at your option) any later version.
9   * 
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18   */
19
20
21 /* Change Activity: */
22 /* End Change Activity */
23
24 #include <linux/proc_fs.h>
25 #include <linux/spinlock.h>
26 #ifndef _ISERIES_PROC_H
27 #include <asm/iSeries/iSeries_proc.h>
28 #endif
29
30
31 static struct proc_dir_entry * iSeries_proc_root = NULL;
32 static int iSeries_proc_initializationDone = 0;
33 static spinlock_t iSeries_proc_lock;
34
35 struct iSeries_proc_registration
36 {
37         struct iSeries_proc_registration *next;
38         iSeriesProcFunction functionMember;
39 };
40
41
42 struct iSeries_proc_registration preallocated[16];
43 #define MYQUEUETYPE(T) struct MYQueue##T
44 #define MYQUEUE(T) \
45 MYQUEUETYPE(T) \
46 { \
47         struct T *head; \
48         struct T *tail; \
49 }
50 #define MYQUEUECTOR(q) do { (q)->head = NULL; (q)->tail = NULL; } while(0)
51 #define MYQUEUEENQ(q, p) \
52 do { \
53         (p)->next = NULL; \
54         if ((q)->head != NULL) { \
55                 (q)->head->next = (p); \
56                 (q)->head = (p); \
57         } else { \
58                 (q)->tail = (q)->head = (p); \
59         } \
60 } while(0)
61
62 #define MYQUEUEDEQ(q,p) \
63 do { \
64         (p) = (q)->tail; \
65         if ((p) != NULL) { \
66                 (q)->tail = (p)->next; \
67                 (p)->next = NULL; \
68         } \
69         if ((q)->tail == NULL) \
70                 (q)->head = NULL; \
71 } while(0)
72 MYQUEUE(iSeries_proc_registration);
73 typedef MYQUEUETYPE(iSeries_proc_registration) aQueue;
74
75
76 aQueue iSeries_free;
77 aQueue iSeries_queued;
78
79 void iSeries_proc_early_init(void)
80 {
81         int i = 0;
82         unsigned long flags;
83         iSeries_proc_initializationDone = 0;
84         spin_lock_init(&iSeries_proc_lock);
85         MYQUEUECTOR(&iSeries_free);
86         MYQUEUECTOR(&iSeries_queued);
87
88         spin_lock_irqsave(&iSeries_proc_lock, flags);
89         for (i = 0; i < 16; ++i) {
90                 MYQUEUEENQ(&iSeries_free, preallocated+i);
91         }
92         spin_unlock_irqrestore(&iSeries_proc_lock, flags);
93 }
94
95 void iSeries_proc_create(void)
96 {
97         unsigned long flags;
98         struct iSeries_proc_registration *reg = NULL;
99         spin_lock_irqsave(&iSeries_proc_lock, flags);
100         printk("iSeries_proc: Creating /proc/iSeries\n");
101
102         iSeries_proc_root = proc_mkdir("iSeries", 0);
103         if (!iSeries_proc_root) return;
104
105         MYQUEUEDEQ(&iSeries_queued, reg);
106
107         while (reg != NULL) {
108                 (*(reg->functionMember))(iSeries_proc_root);
109
110                 MYQUEUEDEQ(&iSeries_queued, reg);
111         }
112
113         iSeries_proc_initializationDone = 1;
114         spin_unlock_irqrestore(&iSeries_proc_lock, flags);
115 }
116
117 void iSeries_proc_callback(iSeriesProcFunction initFunction)
118 {
119         unsigned long flags;
120         spin_lock_irqsave(&iSeries_proc_lock, flags);
121
122         if (iSeries_proc_initializationDone) {
123                 (*initFunction)(iSeries_proc_root);
124         } else {
125                 struct iSeries_proc_registration *reg = NULL;
126
127                 MYQUEUEDEQ(&iSeries_free, reg);
128
129                 if (reg != NULL) {
130                         /* printk("Registering %p in reg %p\n", initFunction, reg); */
131                         reg->functionMember = initFunction;
132
133                         MYQUEUEENQ(&iSeries_queued, reg);
134                 } else {
135                         printk("Couldn't get a queue entry\n");
136                 }
137         }
138
139         spin_unlock_irqrestore(&iSeries_proc_lock, flags);
140 }
141
142