aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@de.ibm.com>2005-06-25 17:55:33 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:37 -0400
commit66a464dbc8e0345b6f972b92bf1118e043d7c987 (patch)
tree4c8f83ce6b1879556025fe77b97629a8380aa4dd /arch
parent6b979de395c7e1b7e59f74a870e1d1911853eccb (diff)
[PATCH] s390: debug feature changes
This patch changes the memory allocation method for the s390 debug feature. Trace buffers had been allocated using the get_free_pages() function before. Therefore it was not possible to get big memory areas in a running system due to memory fragmentation. Now the trace buffers are subdivided into several subbuffers with pagesize. Therefore it is now possible to allocate more memory for the trace buffers and more trace records can be written. In addition to that, dynamic specification of the size of the trace buffers is implemented. It is now possible to change the size of a trace buffer using a new debugfs file instance. When writing a number into this file, the trace buffer size is changed to 'number * pagesize'. In the past all the traces could be obtained from userspace by accessing files in the "proc" filesystem. Now with debugfs we have a new filesystem which should be used for debugging purposes. This patch moves the debug feature from procfs to debugfs. Since the interface of debug_register() changed, all device drivers, which use the debug feature had to be adjusted. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kernel/debug.c820
1 files changed, 535 insertions, 285 deletions
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 91f8ce5543d3..960ba6029c3a 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -19,22 +19,27 @@
19#include <linux/sysctl.h> 19#include <linux/sysctl.h>
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21#include <asm/semaphore.h> 21#include <asm/semaphore.h>
22
23#include <linux/module.h> 22#include <linux/module.h>
24#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/fs.h>
25#include <linux/debugfs.h>
25 26
26#include <asm/debug.h> 27#include <asm/debug.h>
27 28
28#define DEBUG_PROLOG_ENTRY -1 29#define DEBUG_PROLOG_ENTRY -1
29 30
31#define ALL_AREAS 0 /* copy all debug areas */
32#define NO_AREAS 1 /* copy no debug areas */
33
30/* typedefs */ 34/* typedefs */
31 35
32typedef struct file_private_info { 36typedef struct file_private_info {
33 loff_t offset; /* offset of last read in file */ 37 loff_t offset; /* offset of last read in file */
34 int act_area; /* number of last formated area */ 38 int act_area; /* number of last formated area */
39 int act_page; /* act page in given area */
35 int act_entry; /* last formated entry (offset */ 40 int act_entry; /* last formated entry (offset */
36 /* relative to beginning of last */ 41 /* relative to beginning of last */
37 /* formated area) */ 42 /* formated page) */
38 size_t act_entry_offset; /* up to this offset we copied */ 43 size_t act_entry_offset; /* up to this offset we copied */
39 /* in last read the last formated */ 44 /* in last read the last formated */
40 /* entry to userland */ 45 /* entry to userland */
@@ -51,8 +56,8 @@ typedef struct
51 * This assumes that all args are converted into longs 56 * This assumes that all args are converted into longs
52 * on L/390 this is the case for all types of parameter 57 * on L/390 this is the case for all types of parameter
53 * except of floats, and long long (32 bit) 58 * except of floats, and long long (32 bit)
54 * 59 *
55 */ 60 */
56 long args[0]; 61 long args[0];
57} debug_sprintf_entry_t; 62} debug_sprintf_entry_t;
58 63
@@ -63,32 +68,38 @@ extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
63 68
64static int debug_init(void); 69static int debug_init(void);
65static ssize_t debug_output(struct file *file, char __user *user_buf, 70static ssize_t debug_output(struct file *file, char __user *user_buf,
66 size_t user_len, loff_t * offset); 71 size_t user_len, loff_t * offset);
67static ssize_t debug_input(struct file *file, const char __user *user_buf, 72static ssize_t debug_input(struct file *file, const char __user *user_buf,
68 size_t user_len, loff_t * offset); 73 size_t user_len, loff_t * offset);
69static int debug_open(struct inode *inode, struct file *file); 74static int debug_open(struct inode *inode, struct file *file);
70static int debug_close(struct inode *inode, struct file *file); 75static int debug_close(struct inode *inode, struct file *file);
71static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size); 76static debug_info_t* debug_info_create(char *name, int pages_per_area,
77 int nr_areas, int buf_size);
72static void debug_info_get(debug_info_t *); 78static void debug_info_get(debug_info_t *);
73static void debug_info_put(debug_info_t *); 79static void debug_info_put(debug_info_t *);
74static int debug_prolog_level_fn(debug_info_t * id, 80static int debug_prolog_level_fn(debug_info_t * id,
75 struct debug_view *view, char *out_buf); 81 struct debug_view *view, char *out_buf);
76static int debug_input_level_fn(debug_info_t * id, struct debug_view *view, 82static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
77 struct file *file, const char __user *user_buf, 83 struct file *file, const char __user *user_buf,
78 size_t user_buf_size, loff_t * offset); 84 size_t user_buf_size, loff_t * offset);
85static int debug_prolog_pages_fn(debug_info_t * id,
86 struct debug_view *view, char *out_buf);
87static int debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
88 struct file *file, const char __user *user_buf,
89 size_t user_buf_size, loff_t * offset);
79static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view, 90static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
80 struct file *file, const char __user *user_buf, 91 struct file *file, const char __user *user_buf,
81 size_t user_buf_size, loff_t * offset); 92 size_t user_buf_size, loff_t * offset);
82static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view, 93static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
83 char *out_buf, const char *in_buf); 94 char *out_buf, const char *in_buf);
84static int debug_raw_format_fn(debug_info_t * id, 95static int debug_raw_format_fn(debug_info_t * id,
85 struct debug_view *view, char *out_buf, 96 struct debug_view *view, char *out_buf,
86 const char *in_buf); 97 const char *in_buf);
87static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view, 98static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
88 int area, debug_entry_t * entry, char *out_buf); 99 int area, debug_entry_t * entry, char *out_buf);
89 100
90static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view, 101static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
91 char *out_buf, debug_sprintf_entry_t *curr_event); 102 char *out_buf, debug_sprintf_entry_t *curr_event);
92 103
93/* globals */ 104/* globals */
94 105
@@ -119,6 +130,15 @@ struct debug_view debug_level_view = {
119 NULL 130 NULL
120}; 131};
121 132
133struct debug_view debug_pages_view = {
134 "pages",
135 &debug_prolog_pages_fn,
136 NULL,
137 NULL,
138 &debug_input_pages_fn,
139 NULL
140};
141
122struct debug_view debug_flush_view = { 142struct debug_view debug_flush_view = {
123 "flush", 143 "flush",
124 NULL, 144 NULL,
@@ -149,98 +169,161 @@ DECLARE_MUTEX(debug_lock);
149static int initialized; 169static int initialized;
150 170
151static struct file_operations debug_file_ops = { 171static struct file_operations debug_file_ops = {
152 .owner = THIS_MODULE, 172 .owner = THIS_MODULE,
153 .read = debug_output, 173 .read = debug_output,
154 .write = debug_input, 174 .write = debug_input,
155 .open = debug_open, 175 .open = debug_open,
156 .release = debug_close, 176 .release = debug_close,
157}; 177};
158 178
159static struct proc_dir_entry *debug_proc_root_entry; 179static struct dentry *debug_debugfs_root_entry;
160 180
161/* functions */ 181/* functions */
162 182
163/* 183/*
184 * debug_areas_alloc
185 * - Debug areas are implemented as a threedimensonal array:
186 * areas[areanumber][pagenumber][pageoffset]
187 */
188
189static debug_entry_t***
190debug_areas_alloc(int pages_per_area, int nr_areas)
191{
192 debug_entry_t*** areas;
193 int i,j;
194
195 areas = (debug_entry_t ***) kmalloc(nr_areas *
196 sizeof(debug_entry_t**),
197 GFP_KERNEL);
198 if (!areas)
199 goto fail_malloc_areas;
200 for (i = 0; i < nr_areas; i++) {
201 areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
202 sizeof(debug_entry_t*),GFP_KERNEL);
203 if (!areas[i]) {
204 goto fail_malloc_areas2;
205 }
206 for(j = 0; j < pages_per_area; j++) {
207 areas[i][j] = (debug_entry_t*)kmalloc(PAGE_SIZE,
208 GFP_KERNEL);
209 if(!areas[i][j]) {
210 for(j--; j >=0 ; j--) {
211 kfree(areas[i][j]);
212 }
213 kfree(areas[i]);
214 goto fail_malloc_areas2;
215 } else {
216 memset(areas[i][j],0,PAGE_SIZE);
217 }
218 }
219 }
220 return areas;
221
222fail_malloc_areas2:
223 for(i--; i >= 0; i--){
224 for(j=0; j < pages_per_area;j++){
225 kfree(areas[i][j]);
226 }
227 kfree(areas[i]);
228 }
229 kfree(areas);
230fail_malloc_areas:
231 return NULL;
232
233}
234
235
236/*
164 * debug_info_alloc 237 * debug_info_alloc
165 * - alloc new debug-info 238 * - alloc new debug-info
166 */ 239 */
167 240
168static debug_info_t* debug_info_alloc(char *name, int page_order, 241static debug_info_t*
169 int nr_areas, int buf_size) 242debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
243 int level, int mode)
170{ 244{
171 debug_info_t* rc; 245 debug_info_t* rc;
172 int i;
173 246
174 /* alloc everything */ 247 /* alloc everything */
175 248
176 rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC); 249 rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
177 if(!rc) 250 if(!rc)
178 goto fail_malloc_rc; 251 goto fail_malloc_rc;
179 rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC); 252 rc->active_entries = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
180 if(!rc->active_entry) 253 if(!rc->active_entries)
181 goto fail_malloc_active_entry; 254 goto fail_malloc_active_entries;
182 memset(rc->active_entry, 0, nr_areas * sizeof(int)); 255 memset(rc->active_entries, 0, nr_areas * sizeof(int));
183 rc->areas = (debug_entry_t **) kmalloc(nr_areas * 256 rc->active_pages = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
184 sizeof(debug_entry_t *), 257 if(!rc->active_pages)
185 GFP_ATOMIC); 258 goto fail_malloc_active_pages;
186 if (!rc->areas) 259 memset(rc->active_pages, 0, nr_areas * sizeof(int));
187 goto fail_malloc_areas; 260 if((mode == ALL_AREAS) && (pages_per_area != 0)){
188 for (i = 0; i < nr_areas; i++) { 261 rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
189 rc->areas[i] = (debug_entry_t *) __get_free_pages(GFP_ATOMIC, 262 if(!rc->areas)
190 page_order); 263 goto fail_malloc_areas;
191 if (!rc->areas[i]) { 264 } else {
192 for (i--; i >= 0; i--) { 265 rc->areas = NULL;
193 free_pages((unsigned long) rc->areas[i],
194 page_order);
195 }
196 goto fail_malloc_areas2;
197 } else {
198 memset(rc->areas[i], 0, PAGE_SIZE << page_order);
199 }
200 } 266 }
201 267
202 /* initialize members */ 268 /* initialize members */
203 269
204 spin_lock_init(&rc->lock); 270 spin_lock_init(&rc->lock);
205 rc->page_order = page_order; 271 rc->pages_per_area = pages_per_area;
206 rc->nr_areas = nr_areas; 272 rc->nr_areas = nr_areas;
207 rc->active_area = 0; 273 rc->active_area = 0;
208 rc->level = DEBUG_DEFAULT_LEVEL; 274 rc->level = level;
209 rc->buf_size = buf_size; 275 rc->buf_size = buf_size;
210 rc->entry_size = sizeof(debug_entry_t) + buf_size; 276 rc->entry_size = sizeof(debug_entry_t) + buf_size;
211 strlcpy(rc->name, name, sizeof(rc->name)); 277 strlcpy(rc->name, name, sizeof(rc->name)-1);
212 memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *)); 278 memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
213#ifdef CONFIG_PROC_FS 279 memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
214 memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS * 280 sizeof(struct dentry*));
215 sizeof(struct proc_dir_entry*));
216#endif /* CONFIG_PROC_FS */
217 atomic_set(&(rc->ref_count), 0); 281 atomic_set(&(rc->ref_count), 0);
218 282
219 return rc; 283 return rc;
220 284
221fail_malloc_areas2:
222 kfree(rc->areas);
223fail_malloc_areas: 285fail_malloc_areas:
224 kfree(rc->active_entry); 286 kfree(rc->active_pages);
225fail_malloc_active_entry: 287fail_malloc_active_pages:
288 kfree(rc->active_entries);
289fail_malloc_active_entries:
226 kfree(rc); 290 kfree(rc);
227fail_malloc_rc: 291fail_malloc_rc:
228 return NULL; 292 return NULL;
229} 293}
230 294
231/* 295/*
232 * debug_info_free 296 * debug_areas_free
233 * - free memory debug-info 297 * - free all debug areas
234 */ 298 */
235 299
236static void debug_info_free(debug_info_t* db_info){ 300static void
237 int i; 301debug_areas_free(debug_info_t* db_info)
302{
303 int i,j;
304
305 if(!db_info->areas)
306 return;
238 for (i = 0; i < db_info->nr_areas; i++) { 307 for (i = 0; i < db_info->nr_areas; i++) {
239 free_pages((unsigned long) db_info->areas[i], 308 for(j = 0; j < db_info->pages_per_area; j++) {
240 db_info->page_order); 309 kfree(db_info->areas[i][j]);
310 }
311 kfree(db_info->areas[i]);
241 } 312 }
242 kfree(db_info->areas); 313 kfree(db_info->areas);
243 kfree(db_info->active_entry); 314 db_info->areas = NULL;
315}
316
317/*
318 * debug_info_free
319 * - free memory debug-info
320 */
321
322static void
323debug_info_free(debug_info_t* db_info){
324 debug_areas_free(db_info);
325 kfree(db_info->active_entries);
326 kfree(db_info->active_pages);
244 kfree(db_info); 327 kfree(db_info);
245} 328}
246 329
@@ -249,21 +332,22 @@ static void debug_info_free(debug_info_t* db_info){
249 * - create new debug-info 332 * - create new debug-info
250 */ 333 */
251 334
252static debug_info_t* debug_info_create(char *name, int page_order, 335static debug_info_t*
253 int nr_areas, int buf_size) 336debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
254{ 337{
255 debug_info_t* rc; 338 debug_info_t* rc;
256 339
257 rc = debug_info_alloc(name, page_order, nr_areas, buf_size); 340 rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
341 DEBUG_DEFAULT_LEVEL, ALL_AREAS);
258 if(!rc) 342 if(!rc)
259 goto out; 343 goto out;
260 344
261 345 /* create root directory */
262 /* create proc rood directory */ 346 rc->debugfs_root_entry = debugfs_create_dir(rc->name,
263 rc->proc_root_entry = proc_mkdir(rc->name, debug_proc_root_entry); 347 debug_debugfs_root_entry);
264 348
265 /* append new element to linked list */ 349 /* append new element to linked list */
266 if (debug_area_first == NULL) { 350 if (!debug_area_first) {
267 /* first element in list */ 351 /* first element in list */
268 debug_area_first = rc; 352 debug_area_first = rc;
269 rc->prev = NULL; 353 rc->prev = NULL;
@@ -285,17 +369,21 @@ out:
285 * - copy debug-info 369 * - copy debug-info
286 */ 370 */
287 371
288static debug_info_t* debug_info_copy(debug_info_t* in) 372static debug_info_t*
373debug_info_copy(debug_info_t* in, int mode)
289{ 374{
290 int i; 375 int i,j;
291 debug_info_t* rc; 376 debug_info_t* rc;
292 rc = debug_info_alloc(in->name, in->page_order, 377
293 in->nr_areas, in->buf_size); 378 rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas,
294 if(!rc) 379 in->buf_size, in->level, mode);
380 if(!rc || (mode == NO_AREAS))
295 goto out; 381 goto out;
296 382
297 for(i = 0; i < in->nr_areas; i++){ 383 for(i = 0; i < in->nr_areas; i++){
298 memcpy(rc->areas[i],in->areas[i], PAGE_SIZE << in->page_order); 384 for(j = 0; j < in->pages_per_area; j++) {
385 memcpy(rc->areas[i][j], in->areas[i][j],PAGE_SIZE);
386 }
299 } 387 }
300out: 388out:
301 return rc; 389 return rc;
@@ -306,7 +394,8 @@ out:
306 * - increments reference count for debug-info 394 * - increments reference count for debug-info
307 */ 395 */
308 396
309static void debug_info_get(debug_info_t * db_info) 397static void
398debug_info_get(debug_info_t * db_info)
310{ 399{
311 if (db_info) 400 if (db_info)
312 atomic_inc(&db_info->ref_count); 401 atomic_inc(&db_info->ref_count);
@@ -317,29 +406,20 @@ static void debug_info_get(debug_info_t * db_info)
317 * - decreases reference count for debug-info and frees it if necessary 406 * - decreases reference count for debug-info and frees it if necessary
318 */ 407 */
319 408
320static void debug_info_put(debug_info_t *db_info) 409static void
410debug_info_put(debug_info_t *db_info)
321{ 411{
322 int i; 412 int i;
323 413
324 if (!db_info) 414 if (!db_info)
325 return; 415 return;
326 if (atomic_dec_and_test(&db_info->ref_count)) { 416 if (atomic_dec_and_test(&db_info->ref_count)) {
327#ifdef DEBUG
328 printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
329 db_info, db_info->name);
330#endif
331 for (i = 0; i < DEBUG_MAX_VIEWS; i++) { 417 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
332 if (db_info->views[i] == NULL) 418 if (!db_info->views[i])
333 continue; 419 continue;
334#ifdef CONFIG_PROC_FS 420 debugfs_remove(db_info->debugfs_entries[i]);
335 remove_proc_entry(db_info->proc_entries[i]->name,
336 db_info->proc_root_entry);
337#endif
338 } 421 }
339#ifdef CONFIG_PROC_FS 422 debugfs_remove(db_info->debugfs_root_entry);
340 remove_proc_entry(db_info->proc_root_entry->name,
341 debug_proc_root_entry);
342#endif
343 if(db_info == debug_area_first) 423 if(db_info == debug_area_first)
344 debug_area_first = db_info->next; 424 debug_area_first = db_info->next;
345 if(db_info == debug_area_last) 425 if(db_info == debug_area_last)
@@ -355,9 +435,9 @@ static void debug_info_put(debug_info_t *db_info)
355 * - format one debug entry and return size of formated data 435 * - format one debug entry and return size of formated data
356 */ 436 */
357 437
358static int debug_format_entry(file_private_info_t *p_info) 438static int
439debug_format_entry(file_private_info_t *p_info)
359{ 440{
360 debug_info_t *id_org = p_info->debug_info_org;
361 debug_info_t *id_snap = p_info->debug_info_snap; 441 debug_info_t *id_snap = p_info->debug_info_snap;
362 struct debug_view *view = p_info->view; 442 struct debug_view *view = p_info->view;
363 debug_entry_t *act_entry; 443 debug_entry_t *act_entry;
@@ -365,22 +445,23 @@ static int debug_format_entry(file_private_info_t *p_info)
365 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){ 445 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
366 /* print prolog */ 446 /* print prolog */
367 if (view->prolog_proc) 447 if (view->prolog_proc)
368 len += view->prolog_proc(id_org, view,p_info->temp_buf); 448 len += view->prolog_proc(id_snap,view,p_info->temp_buf);
369 goto out; 449 goto out;
370 } 450 }
371 451 if (!id_snap->areas) /* this is true, if we have a prolog only view */
372 act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area] + 452 goto out; /* or if 'pages_per_area' is 0 */
373 p_info->act_entry); 453 act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area]
454 [p_info->act_page] + p_info->act_entry);
374 455
375 if (act_entry->id.stck == 0LL) 456 if (act_entry->id.stck == 0LL)
376 goto out; /* empty entry */ 457 goto out; /* empty entry */
377 if (view->header_proc) 458 if (view->header_proc)
378 len += view->header_proc(id_org, view, p_info->act_area, 459 len += view->header_proc(id_snap, view, p_info->act_area,
379 act_entry, p_info->temp_buf + len); 460 act_entry, p_info->temp_buf + len);
380 if (view->format_proc) 461 if (view->format_proc)
381 len += view->format_proc(id_org, view, p_info->temp_buf + len, 462 len += view->format_proc(id_snap, view, p_info->temp_buf + len,
382 DEBUG_DATA(act_entry)); 463 DEBUG_DATA(act_entry));
383 out: 464out:
384 return len; 465 return len;
385} 466}
386 467
@@ -389,20 +470,30 @@ static int debug_format_entry(file_private_info_t *p_info)
389 * - goto next entry in p_info 470 * - goto next entry in p_info
390 */ 471 */
391 472
392extern inline int debug_next_entry(file_private_info_t *p_info) 473extern inline int
474debug_next_entry(file_private_info_t *p_info)
393{ 475{
394 debug_info_t *id = p_info->debug_info_snap; 476 debug_info_t *id;
477
478 id = p_info->debug_info_snap;
395 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){ 479 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
396 p_info->act_entry = 0; 480 p_info->act_entry = 0;
481 p_info->act_page = 0;
397 goto out; 482 goto out;
398 } 483 }
399 if ((p_info->act_entry += id->entry_size) 484 if(!id->areas)
400 > ((PAGE_SIZE << (id->page_order)) 485 return 1;
401 - id->entry_size)){ 486 p_info->act_entry += id->entry_size;
402 487 /* switch to next page, if we reached the end of the page */
403 /* next area */ 488 if (p_info->act_entry > (PAGE_SIZE - id->entry_size)){
489 /* next page */
404 p_info->act_entry = 0; 490 p_info->act_entry = 0;
405 p_info->act_area++; 491 p_info->act_page += 1;
492 if((p_info->act_page % id->pages_per_area) == 0) {
493 /* next area */
494 p_info->act_area++;
495 p_info->act_page=0;
496 }
406 if(p_info->act_area >= id->nr_areas) 497 if(p_info->act_area >= id->nr_areas)
407 return 1; 498 return 1;
408 } 499 }
@@ -416,13 +507,14 @@ out:
416 * - copies formated debug entries to the user buffer 507 * - copies formated debug entries to the user buffer
417 */ 508 */
418 509
419static ssize_t debug_output(struct file *file, /* file descriptor */ 510static ssize_t
420 char __user *user_buf, /* user buffer */ 511debug_output(struct file *file, /* file descriptor */
421 size_t len, /* length of buffer */ 512 char __user *user_buf, /* user buffer */
422 loff_t *offset) /* offset in the file */ 513 size_t len, /* length of buffer */
514 loff_t *offset) /* offset in the file */
423{ 515{
424 size_t count = 0; 516 size_t count = 0;
425 size_t entry_offset, size = 0; 517 size_t entry_offset;
426 file_private_info_t *p_info; 518 file_private_info_t *p_info;
427 519
428 p_info = ((file_private_info_t *) file->private_data); 520 p_info = ((file_private_info_t *) file->private_data);
@@ -430,27 +522,33 @@ static ssize_t debug_output(struct file *file, /* file descriptor */
430 return -EPIPE; 522 return -EPIPE;
431 if(p_info->act_area >= p_info->debug_info_snap->nr_areas) 523 if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
432 return 0; 524 return 0;
433
434 entry_offset = p_info->act_entry_offset; 525 entry_offset = p_info->act_entry_offset;
435
436 while(count < len){ 526 while(count < len){
437 size = debug_format_entry(p_info); 527 int formatted_line_size;
438 size = min((len - count), (size - entry_offset)); 528 int formatted_line_residue;
439 529 int user_buf_residue;
440 if(size){ 530 size_t copy_size;
441 if (copy_to_user(user_buf + count, 531
442 p_info->temp_buf + entry_offset, size)) 532 formatted_line_size = debug_format_entry(p_info);
443 return -EFAULT; 533 formatted_line_residue = formatted_line_size - entry_offset;
534 user_buf_residue = len-count;
535 copy_size = min(user_buf_residue, formatted_line_residue);
536 if(copy_size){
537 if (copy_to_user(user_buf + count, p_info->temp_buf
538 + entry_offset, copy_size))
539 return -EFAULT;
540 count += copy_size;
541 entry_offset += copy_size;
444 } 542 }
445 count += size; 543 if(copy_size == formatted_line_residue){
446 entry_offset = 0; 544 entry_offset = 0;
447 if(count != len) 545 if(debug_next_entry(p_info))
448 if(debug_next_entry(p_info))
449 goto out; 546 goto out;
547 }
450 } 548 }
451out: 549out:
452 p_info->offset = *offset + count; 550 p_info->offset = *offset + count;
453 p_info->act_entry_offset = size; 551 p_info->act_entry_offset = entry_offset;
454 *offset = p_info->offset; 552 *offset = p_info->offset;
455 return count; 553 return count;
456} 554}
@@ -461,9 +559,9 @@ out:
461 * - calls input function of view 559 * - calls input function of view
462 */ 560 */
463 561
464static ssize_t debug_input(struct file *file, 562static ssize_t
465 const char __user *user_buf, size_t length, 563debug_input(struct file *file, const char __user *user_buf, size_t length,
466 loff_t *offset) 564 loff_t *offset)
467{ 565{
468 int rc = 0; 566 int rc = 0;
469 file_private_info_t *p_info; 567 file_private_info_t *p_info;
@@ -487,26 +585,23 @@ static ssize_t debug_input(struct file *file,
487 * handle 585 * handle
488 */ 586 */
489 587
490static int debug_open(struct inode *inode, struct file *file) 588static int
589debug_open(struct inode *inode, struct file *file)
491{ 590{
492 int i = 0, rc = 0; 591 int i = 0, rc = 0;
493 file_private_info_t *p_info; 592 file_private_info_t *p_info;
494 debug_info_t *debug_info, *debug_info_snapshot; 593 debug_info_t *debug_info, *debug_info_snapshot;
495 594
496#ifdef DEBUG
497 printk("debug_open\n");
498#endif
499 down(&debug_lock); 595 down(&debug_lock);
500 596
501 /* find debug log and view */ 597 /* find debug log and view */
502
503 debug_info = debug_area_first; 598 debug_info = debug_area_first;
504 while(debug_info != NULL){ 599 while(debug_info != NULL){
505 for (i = 0; i < DEBUG_MAX_VIEWS; i++) { 600 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
506 if (debug_info->views[i] == NULL) 601 if (!debug_info->views[i])
507 continue; 602 continue;
508 else if (debug_info->proc_entries[i] == 603 else if (debug_info->debugfs_entries[i] ==
509 PDE(file->f_dentry->d_inode)) { 604 file->f_dentry) {
510 goto found; /* found view ! */ 605 goto found; /* found view ! */
511 } 606 }
512 } 607 }
@@ -516,41 +611,42 @@ static int debug_open(struct inode *inode, struct file *file)
516 rc = -EINVAL; 611 rc = -EINVAL;
517 goto out; 612 goto out;
518 613
519 found: 614found:
520 615
521 /* make snapshot of current debug areas to get it consistent */ 616 /* Make snapshot of current debug areas to get it consistent. */
617 /* To copy all the areas is only needed, if we have a view which */
618 /* formats the debug areas. */
522 619
523 debug_info_snapshot = debug_info_copy(debug_info); 620 if(!debug_info->views[i]->format_proc &&
621 !debug_info->views[i]->header_proc){
622 debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
623 } else {
624 debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
625 }
524 626
525 if(!debug_info_snapshot){ 627 if(!debug_info_snapshot){
526#ifdef DEBUG
527 printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
528#endif
529 rc = -ENOMEM; 628 rc = -ENOMEM;
530 goto out; 629 goto out;
531 } 630 }
532 631 p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
533 if ((file->private_data = 632 GFP_KERNEL);
534 kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) { 633 if(!p_info){
535#ifdef DEBUG 634 if(debug_info_snapshot)
536 printk(KERN_ERR "debug_open: kmalloc failed\n"); 635 debug_info_free(debug_info_snapshot);
537#endif
538 debug_info_free(debug_info_snapshot);
539 rc = -ENOMEM; 636 rc = -ENOMEM;
540 goto out; 637 goto out;
541 } 638 }
542 p_info = (file_private_info_t *) file->private_data;
543 p_info->offset = 0; 639 p_info->offset = 0;
544 p_info->debug_info_snap = debug_info_snapshot; 640 p_info->debug_info_snap = debug_info_snapshot;
545 p_info->debug_info_org = debug_info; 641 p_info->debug_info_org = debug_info;
546 p_info->view = debug_info->views[i]; 642 p_info->view = debug_info->views[i];
547 p_info->act_area = 0; 643 p_info->act_area = 0;
644 p_info->act_page = 0;
548 p_info->act_entry = DEBUG_PROLOG_ENTRY; 645 p_info->act_entry = DEBUG_PROLOG_ENTRY;
549 p_info->act_entry_offset = 0; 646 p_info->act_entry_offset = 0;
550 647 file->private_data = p_info;
551 debug_info_get(debug_info); 648 debug_info_get(debug_info);
552 649out:
553 out:
554 up(&debug_lock); 650 up(&debug_lock);
555 return rc; 651 return rc;
556} 652}
@@ -561,14 +657,13 @@ static int debug_open(struct inode *inode, struct file *file)
561 * - deletes private_data area of the file handle 657 * - deletes private_data area of the file handle
562 */ 658 */
563 659
564static int debug_close(struct inode *inode, struct file *file) 660static int
661debug_close(struct inode *inode, struct file *file)
565{ 662{
566 file_private_info_t *p_info; 663 file_private_info_t *p_info;
567#ifdef DEBUG
568 printk("debug_close\n");
569#endif
570 p_info = (file_private_info_t *) file->private_data; 664 p_info = (file_private_info_t *) file->private_data;
571 debug_info_free(p_info->debug_info_snap); 665 if(p_info->debug_info_snap)
666 debug_info_free(p_info->debug_info_snap);
572 debug_info_put(p_info->debug_info_org); 667 debug_info_put(p_info->debug_info_org);
573 kfree(file->private_data); 668 kfree(file->private_data);
574 return 0; /* success */ 669 return 0; /* success */
@@ -580,8 +675,8 @@ static int debug_close(struct inode *inode, struct file *file)
580 * - returns handle for debug area 675 * - returns handle for debug area
581 */ 676 */
582 677
583debug_info_t *debug_register 678debug_info_t*
584 (char *name, int page_order, int nr_areas, int buf_size) 679debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
585{ 680{
586 debug_info_t *rc = NULL; 681 debug_info_t *rc = NULL;
587 682
@@ -591,18 +686,14 @@ debug_info_t *debug_register
591 686
592 /* create new debug_info */ 687 /* create new debug_info */
593 688
594 rc = debug_info_create(name, page_order, nr_areas, buf_size); 689 rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
595 if(!rc) 690 if(!rc)
596 goto out; 691 goto out;
597 debug_register_view(rc, &debug_level_view); 692 debug_register_view(rc, &debug_level_view);
598 debug_register_view(rc, &debug_flush_view); 693 debug_register_view(rc, &debug_flush_view);
599#ifdef DEBUG 694 debug_register_view(rc, &debug_pages_view);
600 printk(KERN_INFO 695out:
601 "debug: reserved %d areas of %d pages for debugging %s\n", 696 if (!rc){
602 nr_areas, 1 << page_order, rc->name);
603#endif
604 out:
605 if (rc == NULL){
606 printk(KERN_ERR "debug: debug_register failed for %s\n",name); 697 printk(KERN_ERR "debug: debug_register failed for %s\n",name);
607 } 698 }
608 up(&debug_lock); 699 up(&debug_lock);
@@ -614,27 +705,65 @@ debug_info_t *debug_register
614 * - give back debug area 705 * - give back debug area
615 */ 706 */
616 707
617void debug_unregister(debug_info_t * id) 708void
709debug_unregister(debug_info_t * id)
618{ 710{
619 if (!id) 711 if (!id)
620 goto out; 712 goto out;
621 down(&debug_lock); 713 down(&debug_lock);
622#ifdef DEBUG
623 printk(KERN_INFO "debug: unregistering %s\n", id->name);
624#endif
625 debug_info_put(id); 714 debug_info_put(id);
626 up(&debug_lock); 715 up(&debug_lock);
627 716
628 out: 717out:
629 return; 718 return;
630} 719}
631 720
632/* 721/*
722 * debug_set_size:
723 * - set area size (number of pages) and number of areas
724 */
725static int
726debug_set_size(debug_info_t* id, int nr_areas, int pages_per_area)
727{
728 unsigned long flags;
729 debug_entry_t *** new_areas;
730 int rc=0;
731
732 if(!id || (nr_areas <= 0) || (pages_per_area < 0))
733 return -EINVAL;
734 if(pages_per_area > 0){
735 new_areas = debug_areas_alloc(pages_per_area, nr_areas);
736 if(!new_areas) {
737 printk(KERN_WARNING "debug: could not allocate memory "\
738 "for pagenumber: %i\n",pages_per_area);
739 rc = -ENOMEM;
740 goto out;
741 }
742 } else {
743 new_areas = NULL;
744 }
745 spin_lock_irqsave(&id->lock,flags);
746 debug_areas_free(id);
747 id->areas = new_areas;
748 id->nr_areas = nr_areas;
749 id->pages_per_area = pages_per_area;
750 id->active_area = 0;
751 memset(id->active_entries,0,sizeof(int)*id->nr_areas);
752 memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
753 spin_unlock_irqrestore(&id->lock,flags);
754 printk(KERN_INFO "debug: %s: set new size (%i pages)\n"\
755 ,id->name, pages_per_area);
756out:
757 return rc;
758}
759
760/*
633 * debug_set_level: 761 * debug_set_level:
634 * - set actual debug level 762 * - set actual debug level
635 */ 763 */
636 764
637void debug_set_level(debug_info_t* id, int new_level) 765void
766debug_set_level(debug_info_t* id, int new_level)
638{ 767{
639 unsigned long flags; 768 unsigned long flags;
640 if(!id) 769 if(!id)
@@ -649,10 +778,6 @@ void debug_set_level(debug_info_t* id, int new_level)
649 id->name, new_level, 0, DEBUG_MAX_LEVEL); 778 id->name, new_level, 0, DEBUG_MAX_LEVEL);
650 } else { 779 } else {
651 id->level = new_level; 780 id->level = new_level;
652#ifdef DEBUG
653 printk(KERN_INFO
654 "debug: %s: new level %i\n",id->name,id->level);
655#endif
656 } 781 }
657 spin_unlock_irqrestore(&id->lock,flags); 782 spin_unlock_irqrestore(&id->lock,flags);
658} 783}
@@ -663,11 +788,16 @@ void debug_set_level(debug_info_t* id, int new_level)
663 * - set active entry to next in the ring buffer 788 * - set active entry to next in the ring buffer
664 */ 789 */
665 790
666extern inline void proceed_active_entry(debug_info_t * id) 791extern inline void
792proceed_active_entry(debug_info_t * id)
667{ 793{
668 if ((id->active_entry[id->active_area] += id->entry_size) 794 if ((id->active_entries[id->active_area] += id->entry_size)
669 > ((PAGE_SIZE << (id->page_order)) - id->entry_size)) 795 > (PAGE_SIZE - id->entry_size)){
670 id->active_entry[id->active_area] = 0; 796 id->active_entries[id->active_area] = 0;
797 id->active_pages[id->active_area] =
798 (id->active_pages[id->active_area] + 1) %
799 id->pages_per_area;
800 }
671} 801}
672 802
673/* 803/*
@@ -675,7 +805,8 @@ extern inline void proceed_active_entry(debug_info_t * id)
675 * - set active area to next in the ring buffer 805 * - set active area to next in the ring buffer
676 */ 806 */
677 807
678extern inline void proceed_active_area(debug_info_t * id) 808extern inline void
809proceed_active_area(debug_info_t * id)
679{ 810{
680 id->active_area++; 811 id->active_area++;
681 id->active_area = id->active_area % id->nr_areas; 812 id->active_area = id->active_area % id->nr_areas;
@@ -685,10 +816,12 @@ extern inline void proceed_active_area(debug_info_t * id)
685 * get_active_entry: 816 * get_active_entry:
686 */ 817 */
687 818
688extern inline debug_entry_t *get_active_entry(debug_info_t * id) 819extern inline debug_entry_t*
820get_active_entry(debug_info_t * id)
689{ 821{
690 return (debug_entry_t *) ((char *) id->areas[id->active_area] + 822 return (debug_entry_t *) (((char *) id->areas[id->active_area]
691 id->active_entry[id->active_area]); 823 [id->active_pages[id->active_area]]) +
824 id->active_entries[id->active_area]);
692} 825}
693 826
694/* 827/*
@@ -696,8 +829,9 @@ extern inline debug_entry_t *get_active_entry(debug_info_t * id)
696 * - set timestamp, caller address, cpu number etc. 829 * - set timestamp, caller address, cpu number etc.
697 */ 830 */
698 831
699extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active, 832extern inline void
700 int level, int exception) 833debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
834 int exception)
701{ 835{
702 STCK(active->id.stck); 836 STCK(active->id.stck);
703 active->id.fields.cpuid = smp_processor_id(); 837 active->id.fields.cpuid = smp_processor_id();
@@ -721,7 +855,8 @@ static int debug_active=1;
721 * always allow read, allow write only if debug_stoppable is set or 855 * always allow read, allow write only if debug_stoppable is set or
722 * if debug_active is already off 856 * if debug_active is already off
723 */ 857 */
724static int s390dbf_procactive(ctl_table *table, int write, struct file *filp, 858static int
859s390dbf_procactive(ctl_table *table, int write, struct file *filp,
725 void __user *buffer, size_t *lenp, loff_t *ppos) 860 void __user *buffer, size_t *lenp, loff_t *ppos)
726{ 861{
727 if (!write || debug_stoppable || !debug_active) 862 if (!write || debug_stoppable || !debug_active)
@@ -766,7 +901,8 @@ static struct ctl_table s390dbf_dir_table[] = {
766 901
767struct ctl_table_header *s390dbf_sysctl_header; 902struct ctl_table_header *s390dbf_sysctl_header;
768 903
769void debug_stop_all(void) 904void
905debug_stop_all(void)
770{ 906{
771 if (debug_stoppable) 907 if (debug_stoppable)
772 debug_active = 0; 908 debug_active = 0;
@@ -778,13 +914,13 @@ void debug_stop_all(void)
778 * - write debug entry with given size 914 * - write debug entry with given size
779 */ 915 */
780 916
781debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf, 917debug_entry_t*
782 int len) 918debug_event_common(debug_info_t * id, int level, const void *buf, int len)
783{ 919{
784 unsigned long flags; 920 unsigned long flags;
785 debug_entry_t *active; 921 debug_entry_t *active;
786 922
787 if (!debug_active) 923 if (!debug_active || !id->areas)
788 return NULL; 924 return NULL;
789 spin_lock_irqsave(&id->lock, flags); 925 spin_lock_irqsave(&id->lock, flags);
790 active = get_active_entry(id); 926 active = get_active_entry(id);
@@ -801,13 +937,13 @@ debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
801 * - write debug entry with given size and switch to next debug area 937 * - write debug entry with given size and switch to next debug area
802 */ 938 */
803 939
804debug_entry_t *debug_exception_common(debug_info_t * id, int level, 940debug_entry_t
805 const void *buf, int len) 941*debug_exception_common(debug_info_t * id, int level, const void *buf, int len)
806{ 942{
807 unsigned long flags; 943 unsigned long flags;
808 debug_entry_t *active; 944 debug_entry_t *active;
809 945
810 if (!debug_active) 946 if (!debug_active || !id->areas)
811 return NULL; 947 return NULL;
812 spin_lock_irqsave(&id->lock, flags); 948 spin_lock_irqsave(&id->lock, flags);
813 active = get_active_entry(id); 949 active = get_active_entry(id);
@@ -823,7 +959,8 @@ debug_entry_t *debug_exception_common(debug_info_t * id, int level,
823 * counts arguments in format string for sprintf view 959 * counts arguments in format string for sprintf view
824 */ 960 */
825 961
826extern inline int debug_count_numargs(char *string) 962extern inline int
963debug_count_numargs(char *string)
827{ 964{
828 int numargs=0; 965 int numargs=0;
829 966
@@ -838,8 +975,8 @@ extern inline int debug_count_numargs(char *string)
838 * debug_sprintf_event: 975 * debug_sprintf_event:
839 */ 976 */
840 977
841debug_entry_t *debug_sprintf_event(debug_info_t* id, 978debug_entry_t*
842 int level,char *string,...) 979debug_sprintf_event(debug_info_t* id, int level,char *string,...)
843{ 980{
844 va_list ap; 981 va_list ap;
845 int numargs,idx; 982 int numargs,idx;
@@ -849,7 +986,7 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
849 986
850 if((!id) || (level > id->level)) 987 if((!id) || (level > id->level))
851 return NULL; 988 return NULL;
852 if (!debug_active) 989 if (!debug_active || !id->areas)
853 return NULL; 990 return NULL;
854 numargs=debug_count_numargs(string); 991 numargs=debug_count_numargs(string);
855 992
@@ -871,8 +1008,8 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
871 * debug_sprintf_exception: 1008 * debug_sprintf_exception:
872 */ 1009 */
873 1010
874debug_entry_t *debug_sprintf_exception(debug_info_t* id, 1011debug_entry_t*
875 int level,char *string,...) 1012debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
876{ 1013{
877 va_list ap; 1014 va_list ap;
878 int numargs,idx; 1015 int numargs,idx;
@@ -882,7 +1019,7 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
882 1019
883 if((!id) || (level > id->level)) 1020 if((!id) || (level > id->level))
884 return NULL; 1021 return NULL;
885 if (!debug_active) 1022 if (!debug_active || !id->areas)
886 return NULL; 1023 return NULL;
887 1024
888 numargs=debug_count_numargs(string); 1025 numargs=debug_count_numargs(string);
@@ -906,15 +1043,14 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
906 * - is called exactly once to initialize the debug feature 1043 * - is called exactly once to initialize the debug feature
907 */ 1044 */
908 1045
909static int __init debug_init(void) 1046static int
1047__init debug_init(void)
910{ 1048{
911 int rc = 0; 1049 int rc = 0;
912 1050
913 s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1); 1051 s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
914 down(&debug_lock); 1052 down(&debug_lock);
915#ifdef CONFIG_PROC_FS 1053 debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
916 debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
917#endif /* CONFIG_PROC_FS */
918 printk(KERN_INFO "debug: Initialization complete\n"); 1054 printk(KERN_INFO "debug: Initialization complete\n");
919 initialized = 1; 1055 initialized = 1;
920 up(&debug_lock); 1056 up(&debug_lock);
@@ -926,13 +1062,14 @@ static int __init debug_init(void)
926 * debug_register_view: 1062 * debug_register_view:
927 */ 1063 */
928 1064
929int debug_register_view(debug_info_t * id, struct debug_view *view) 1065int
1066debug_register_view(debug_info_t * id, struct debug_view *view)
930{ 1067{
931 int rc = 0; 1068 int rc = 0;
932 int i; 1069 int i;
933 unsigned long flags; 1070 unsigned long flags;
934 mode_t mode = S_IFREG; 1071 mode_t mode = S_IFREG;
935 struct proc_dir_entry *pde; 1072 struct dentry *pde;
936 1073
937 if (!id) 1074 if (!id)
938 goto out; 1075 goto out;
@@ -940,16 +1077,17 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
940 mode |= S_IRUSR; 1077 mode |= S_IRUSR;
941 if (view->input_proc) 1078 if (view->input_proc)
942 mode |= S_IWUSR; 1079 mode |= S_IWUSR;
943 pde = create_proc_entry(view->name, mode, id->proc_root_entry); 1080 pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
1081 NULL, &debug_file_ops);
944 if (!pde){ 1082 if (!pde){
945 printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name); 1083 printk(KERN_WARNING "debug: debugfs_create_file() failed!"\
1084 " Cannot register view %s/%s\n", id->name,view->name);
946 rc = -1; 1085 rc = -1;
947 goto out; 1086 goto out;
948 } 1087 }
949
950 spin_lock_irqsave(&id->lock, flags); 1088 spin_lock_irqsave(&id->lock, flags);
951 for (i = 0; i < DEBUG_MAX_VIEWS; i++) { 1089 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
952 if (id->views[i] == NULL) 1090 if (!id->views[i])
953 break; 1091 break;
954 } 1092 }
955 if (i == DEBUG_MAX_VIEWS) { 1093 if (i == DEBUG_MAX_VIEWS) {
@@ -957,16 +1095,14 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
957 id->name,view->name); 1095 id->name,view->name);
958 printk(KERN_WARNING 1096 printk(KERN_WARNING
959 "debug: maximum number of views reached (%i)!\n", i); 1097 "debug: maximum number of views reached (%i)!\n", i);
960 remove_proc_entry(pde->name, id->proc_root_entry); 1098 debugfs_remove(pde);
961 rc = -1; 1099 rc = -1;
962 } 1100 } else {
963 else {
964 id->views[i] = view; 1101 id->views[i] = view;
965 pde->proc_fops = &debug_file_ops; 1102 id->debugfs_entries[i] = pde;
966 id->proc_entries[i] = pde;
967 } 1103 }
968 spin_unlock_irqrestore(&id->lock, flags); 1104 spin_unlock_irqrestore(&id->lock, flags);
969 out: 1105out:
970 return rc; 1106 return rc;
971} 1107}
972 1108
@@ -974,7 +1110,8 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
974 * debug_unregister_view: 1110 * debug_unregister_view:
975 */ 1111 */
976 1112
977int debug_unregister_view(debug_info_t * id, struct debug_view *view) 1113int
1114debug_unregister_view(debug_info_t * id, struct debug_view *view)
978{ 1115{
979 int rc = 0; 1116 int rc = 0;
980 int i; 1117 int i;
@@ -990,15 +1127,46 @@ int debug_unregister_view(debug_info_t * id, struct debug_view *view)
990 if (i == DEBUG_MAX_VIEWS) 1127 if (i == DEBUG_MAX_VIEWS)
991 rc = -1; 1128 rc = -1;
992 else { 1129 else {
993#ifdef CONFIG_PROC_FS 1130 debugfs_remove(id->debugfs_entries[i]);
994 remove_proc_entry(id->proc_entries[i]->name,
995 id->proc_root_entry);
996#endif
997 id->views[i] = NULL; 1131 id->views[i] = NULL;
998 rc = 0; 1132 rc = 0;
999 } 1133 }
1000 spin_unlock_irqrestore(&id->lock, flags); 1134 spin_unlock_irqrestore(&id->lock, flags);
1001 out: 1135out:
1136 return rc;
1137}
1138
1139static inline char *
1140debug_get_user_string(const char __user *user_buf, size_t user_len)
1141{
1142 char* buffer;
1143
1144 buffer = kmalloc(user_len + 1, GFP_KERNEL);
1145 if (!buffer)
1146 return ERR_PTR(-ENOMEM);
1147 if (copy_from_user(buffer, user_buf, user_len) != 0) {
1148 kfree(buffer);
1149 return ERR_PTR(-EFAULT);
1150 }
1151 /* got the string, now strip linefeed. */
1152 if (buffer[user_len - 1] == '\n')
1153 buffer[user_len - 1] = 0;
1154 else
1155 buffer[user_len] = 0;
1156 return buffer;
1157}
1158
1159static inline int
1160debug_get_uint(char *buf)
1161{
1162 int rc;
1163
1164 for(; isspace(*buf); buf++);
1165 rc = simple_strtoul(buf, &buf, 10);
1166 if(*buf){
1167 printk("debug: no integer specified!\n");
1168 rc = -EINVAL;
1169 }
1002 return rc; 1170 return rc;
1003} 1171}
1004 1172
@@ -1011,13 +1179,69 @@ int debug_unregister_view(debug_info_t * id, struct debug_view *view)
1011 * prints out actual debug level 1179 * prints out actual debug level
1012 */ 1180 */
1013 1181
1014static int debug_prolog_level_fn(debug_info_t * id, 1182static int
1183debug_prolog_pages_fn(debug_info_t * id,
1015 struct debug_view *view, char *out_buf) 1184 struct debug_view *view, char *out_buf)
1016{ 1185{
1186 return sprintf(out_buf, "%i\n", id->pages_per_area);
1187}
1188
1189/*
1190 * reads new size (number of pages per debug area)
1191 */
1192
1193static int
1194debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
1195 struct file *file, const char __user *user_buf,
1196 size_t user_len, loff_t * offset)
1197{
1198 char *str;
1199 int rc,new_pages;
1200
1201 if (user_len > 0x10000)
1202 user_len = 0x10000;
1203 if (*offset != 0){
1204 rc = -EPIPE;
1205 goto out;
1206 }
1207 str = debug_get_user_string(user_buf,user_len);
1208 if(IS_ERR(str)){
1209 rc = PTR_ERR(str);
1210 goto out;
1211 }
1212 new_pages = debug_get_uint(str);
1213 if(new_pages < 0){
1214 rc = -EINVAL;
1215 goto free_str;
1216 }
1217 rc = debug_set_size(id,id->nr_areas, new_pages);
1218 if(rc != 0){
1219 rc = -EINVAL;
1220 goto free_str;
1221 }
1222 rc = user_len;
1223free_str:
1224 kfree(str);
1225out:
1226 *offset += user_len;
1227 return rc; /* number of input characters */
1228}
1229
1230/*
1231 * prints out actual debug level
1232 */
1233
1234static int
1235debug_prolog_level_fn(debug_info_t * id, struct debug_view *view, char *out_buf)
1236{
1017 int rc = 0; 1237 int rc = 0;
1018 1238
1019 if(id->level == -1) rc = sprintf(out_buf,"-\n"); 1239 if(id->level == DEBUG_OFF_LEVEL) {
1020 else rc = sprintf(out_buf, "%i\n", id->level); 1240 rc = sprintf(out_buf,"-\n");
1241 }
1242 else {
1243 rc = sprintf(out_buf, "%i\n", id->level);
1244 }
1021 return rc; 1245 return rc;
1022} 1246}
1023 1247
@@ -1025,30 +1249,43 @@ static int debug_prolog_level_fn(debug_info_t * id,
1025 * reads new debug level 1249 * reads new debug level
1026 */ 1250 */
1027 1251
1028static int debug_input_level_fn(debug_info_t * id, struct debug_view *view, 1252static int
1029 struct file *file, const char __user *user_buf, 1253debug_input_level_fn(debug_info_t * id, struct debug_view *view,
1030 size_t in_buf_size, loff_t * offset) 1254 struct file *file, const char __user *user_buf,
1255 size_t user_len, loff_t * offset)
1031{ 1256{
1032 char input_buf[1]; 1257 char *str;
1033 int rc = in_buf_size; 1258 int rc,new_level;
1034 1259
1035 if (*offset != 0) 1260 if (user_len > 0x10000)
1261 user_len = 0x10000;
1262 if (*offset != 0){
1263 rc = -EPIPE;
1036 goto out; 1264 goto out;
1037 if (copy_from_user(input_buf, user_buf, 1)){ 1265 }
1038 rc = -EFAULT; 1266 str = debug_get_user_string(user_buf,user_len);
1267 if(IS_ERR(str)){
1268 rc = PTR_ERR(str);
1039 goto out; 1269 goto out;
1040 } 1270 }
1041 if (isdigit(input_buf[0])) { 1271 if(str[0] == '-'){
1042 int new_level = ((int) input_buf[0] - (int) '0');
1043 debug_set_level(id, new_level);
1044 } else if(input_buf[0] == '-') {
1045 debug_set_level(id, DEBUG_OFF_LEVEL); 1272 debug_set_level(id, DEBUG_OFF_LEVEL);
1273 rc = user_len;
1274 goto free_str;
1046 } else { 1275 } else {
1047 printk(KERN_INFO "debug: level `%c` is not valid\n", 1276 new_level = debug_get_uint(str);
1048 input_buf[0]);
1049 } 1277 }
1050 out: 1278 if(new_level < 0) {
1051 *offset += in_buf_size; 1279 printk(KERN_INFO "debug: level `%s` is not valid\n", str);
1280 rc = -EINVAL;
1281 } else {
1282 debug_set_level(id, new_level);
1283 rc = user_len;
1284 }
1285free_str:
1286 kfree(str);
1287out:
1288 *offset += user_len;
1052 return rc; /* number of input characters */ 1289 return rc; /* number of input characters */
1053} 1290}
1054 1291
@@ -1057,29 +1294,36 @@ static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
1057 * flushes debug areas 1294 * flushes debug areas
1058 */ 1295 */
1059 1296
1060void debug_flush(debug_info_t* id, int area) 1297void
1298debug_flush(debug_info_t* id, int area)
1061{ 1299{
1062 unsigned long flags; 1300 unsigned long flags;
1063 int i; 1301 int i,j;
1064 1302
1065 if(!id) 1303 if(!id || !id->areas)
1066 return; 1304 return;
1067 spin_lock_irqsave(&id->lock,flags); 1305 spin_lock_irqsave(&id->lock,flags);
1068 if(area == DEBUG_FLUSH_ALL){ 1306 if(area == DEBUG_FLUSH_ALL){
1069 id->active_area = 0; 1307 id->active_area = 0;
1070 memset(id->active_entry, 0, id->nr_areas * sizeof(int)); 1308 memset(id->active_entries, 0, id->nr_areas * sizeof(int));
1071 for (i = 0; i < id->nr_areas; i++) 1309 for (i = 0; i < id->nr_areas; i++) {
1072 memset(id->areas[i], 0, PAGE_SIZE << id->page_order); 1310 id->active_pages[i] = 0;
1311 for(j = 0; j < id->pages_per_area; j++) {
1312 memset(id->areas[i][j], 0, PAGE_SIZE);
1313 }
1314 }
1073 printk(KERN_INFO "debug: %s: all areas flushed\n",id->name); 1315 printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
1074 } else if(area >= 0 && area < id->nr_areas) { 1316 } else if(area >= 0 && area < id->nr_areas) {
1075 id->active_entry[area] = 0; 1317 id->active_entries[area] = 0;
1076 memset(id->areas[area], 0, PAGE_SIZE << id->page_order); 1318 id->active_pages[area] = 0;
1077 printk(KERN_INFO 1319 for(i = 0; i < id->pages_per_area; i++) {
1078 "debug: %s: area %i has been flushed\n", 1320 memset(id->areas[area][i],0,PAGE_SIZE);
1321 }
1322 printk(KERN_INFO "debug: %s: area %i has been flushed\n",
1079 id->name, area); 1323 id->name, area);
1080 } else { 1324 } else {
1081 printk(KERN_INFO 1325 printk(KERN_INFO
1082 "debug: %s: area %i cannot be flushed (range: %i - %i)\n", 1326 "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
1083 id->name, area, 0, id->nr_areas-1); 1327 id->name, area, 0, id->nr_areas-1);
1084 } 1328 }
1085 spin_unlock_irqrestore(&id->lock,flags); 1329 spin_unlock_irqrestore(&id->lock,flags);
@@ -1089,15 +1333,20 @@ void debug_flush(debug_info_t* id, int area)
1089 * view function: flushes debug areas 1333 * view function: flushes debug areas
1090 */ 1334 */
1091 1335
1092static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view, 1336static int
1093 struct file *file, const char __user *user_buf, 1337debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1094 size_t in_buf_size, loff_t * offset) 1338 struct file *file, const char __user *user_buf,
1339 size_t user_len, loff_t * offset)
1095{ 1340{
1096 char input_buf[1]; 1341 char input_buf[1];
1097 int rc = in_buf_size; 1342 int rc = user_len;
1098 1343
1099 if (*offset != 0) 1344 if (user_len > 0x10000)
1345 user_len = 0x10000;
1346 if (*offset != 0){
1347 rc = -EPIPE;
1100 goto out; 1348 goto out;
1349 }
1101 if (copy_from_user(input_buf, user_buf, 1)){ 1350 if (copy_from_user(input_buf, user_buf, 1)){
1102 rc = -EFAULT; 1351 rc = -EFAULT;
1103 goto out; 1352 goto out;
@@ -1114,8 +1363,8 @@ static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1114 1363
1115 printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]); 1364 printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
1116 1365
1117 out: 1366out:
1118 *offset += in_buf_size; 1367 *offset += user_len;
1119 return rc; /* number of input characters */ 1368 return rc; /* number of input characters */
1120} 1369}
1121 1370
@@ -1123,8 +1372,9 @@ static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1123 * prints debug header in raw format 1372 * prints debug header in raw format
1124 */ 1373 */
1125 1374
1126int debug_raw_header_fn(debug_info_t * id, struct debug_view *view, 1375static int
1127 int area, debug_entry_t * entry, char *out_buf) 1376debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1377 int area, debug_entry_t * entry, char *out_buf)
1128{ 1378{
1129 int rc; 1379 int rc;
1130 1380
@@ -1137,7 +1387,8 @@ int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1137 * prints debug data in raw format 1387 * prints debug data in raw format
1138 */ 1388 */
1139 1389
1140static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view, 1390static int
1391debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1141 char *out_buf, const char *in_buf) 1392 char *out_buf, const char *in_buf)
1142{ 1393{
1143 int rc; 1394 int rc;
@@ -1151,8 +1402,9 @@ static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1151 * prints debug data in hex/ascii format 1402 * prints debug data in hex/ascii format
1152 */ 1403 */
1153 1404
1154static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view, 1405static int
1155 char *out_buf, const char *in_buf) 1406debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1407 char *out_buf, const char *in_buf)
1156{ 1408{
1157 int i, rc = 0; 1409 int i, rc = 0;
1158 1410
@@ -1176,7 +1428,8 @@ static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1176 * prints header for debug entry 1428 * prints header for debug entry
1177 */ 1429 */
1178 1430
1179int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, 1431int
1432debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1180 int area, debug_entry_t * entry, char *out_buf) 1433 int area, debug_entry_t * entry, char *out_buf)
1181{ 1434{
1182 struct timeval time_val; 1435 struct timeval time_val;
@@ -1210,8 +1463,9 @@ int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1210 1463
1211#define DEBUG_SPRINTF_MAX_ARGS 10 1464#define DEBUG_SPRINTF_MAX_ARGS 10
1212 1465
1213int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view, 1466static int
1214 char *out_buf, debug_sprintf_entry_t *curr_event) 1467debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
1468 char *out_buf, debug_sprintf_entry_t *curr_event)
1215{ 1469{
1216 int num_longs, num_used_args = 0,i, rc = 0; 1470 int num_longs, num_used_args = 0,i, rc = 0;
1217 int index[DEBUG_SPRINTF_MAX_ARGS]; 1471 int index[DEBUG_SPRINTF_MAX_ARGS];
@@ -1251,14 +1505,10 @@ out:
1251/* 1505/*
1252 * clean up module 1506 * clean up module
1253 */ 1507 */
1254void __exit debug_exit(void) 1508void
1509__exit debug_exit(void)
1255{ 1510{
1256#ifdef DEBUG 1511 debugfs_remove(debug_debugfs_root_entry);
1257 printk("debug_cleanup_module: \n");
1258#endif
1259#ifdef CONFIG_PROC_FS
1260 remove_proc_entry(debug_proc_root_entry->name, NULL);
1261#endif /* CONFIG_PROC_FS */
1262 unregister_sysctl_table(s390dbf_sysctl_header); 1512 unregister_sysctl_table(s390dbf_sysctl_header);
1263 return; 1513 return;
1264} 1514}
@@ -1266,7 +1516,7 @@ void __exit debug_exit(void)
1266/* 1516/*
1267 * module definitions 1517 * module definitions
1268 */ 1518 */
1269core_initcall(debug_init); 1519postcore_initcall(debug_init);
1270module_exit(debug_exit); 1520module_exit(debug_exit);
1271MODULE_LICENSE("GPL"); 1521MODULE_LICENSE("GPL");
1272 1522