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 31static struct proc_dir_entry * iSeries_proc_root = NULL; 32static int iSeries_proc_initializationDone = 0; 33static spinlock_t iSeries_proc_lock; 34 35struct iSeries_proc_registration 36{ 37 struct iSeries_proc_registration *next; 38 iSeriesProcFunction functionMember; 39}; 40 41 42struct iSeries_proc_registration preallocated[16]; 43#define MYQUEUETYPE(T) struct MYQueue##T 44#define MYQUEUE(T) \ 45MYQUEUETYPE(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) \ 52do { \ 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) \ 63do { \ 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) 72MYQUEUE(iSeries_proc_registration); 73typedef MYQUEUETYPE(iSeries_proc_registration) aQueue; 74 75 76aQueue iSeries_free; 77aQueue iSeries_queued; 78 79void 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 95void 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 117void 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