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
iSeries_proc_early_init(void)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
iSeries_proc_create(void)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
iSeries_proc_callback(iSeriesProcFunction initFunction)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
143