OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [arch/] [s390/] [kernel/] [debug.c] - Blame information for rev 63

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 63 marcus.erl
/*
2
 *  arch/s390/kernel/debug.c
3
 *   S/390 debug facility
4
 *
5
 *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
6
 *                             IBM Corporation
7
 *    Author(s): Michael Holzheu (holzheu@de.ibm.com),
8
 *               Holger Smolinski (Holger.Smolinski@de.ibm.com)
9
 *
10
 *    Bugreports to: <Linux390@de.ibm.com>
11
 */
12
 
13
#include <linux/stddef.h>
14
#include <linux/kernel.h>
15
#include <linux/errno.h>
16
#include <linux/slab.h>
17
#include <linux/ctype.h>
18
#include <linux/sysctl.h>
19
#include <asm/uaccess.h>
20
#include <asm/semaphore.h>
21
#include <linux/module.h>
22
#include <linux/init.h>
23
#include <linux/fs.h>
24
#include <linux/debugfs.h>
25
 
26
#include <asm/debug.h>
27
 
28
#define DEBUG_PROLOG_ENTRY -1
29
 
30
#define ALL_AREAS 0 /* copy all debug areas */
31
#define NO_AREAS  1 /* copy no debug areas */
32
 
33
/* typedefs */
34
 
35
typedef struct file_private_info {
36
        loff_t offset;                  /* offset of last read in file */
37
        int    act_area;                /* number of last formated area */
38
        int    act_page;                /* act page in given area */
39
        int    act_entry;               /* last formated entry (offset */
40
                                        /* relative to beginning of last */
41
                                        /* formated page) */
42
        size_t act_entry_offset;        /* up to this offset we copied */
43
                                        /* in last read the last formated */
44
                                        /* entry to userland */
45
        char   temp_buf[2048];          /* buffer for output */
46
        debug_info_t *debug_info_org;   /* original debug information */
47
        debug_info_t *debug_info_snap;  /* snapshot of debug information */
48
        struct debug_view *view;        /* used view of debug info */
49
} file_private_info_t;
50
 
51
typedef struct
52
{
53
        char *string;
54
        /*
55
         * This assumes that all args are converted into longs
56
         * on L/390 this is the case for all types of parameter
57
         * except of floats, and long long (32 bit)
58
         *
59
         */
60
        long args[0];
61
} debug_sprintf_entry_t;
62
 
63
 
64
extern void tod_to_timeval(uint64_t todval, struct timespec *xtime);
65
 
66
/* internal function prototyes */
67
 
68
static int debug_init(void);
69
static ssize_t debug_output(struct file *file, char __user *user_buf,
70
                        size_t user_len, loff_t * offset);
71
static ssize_t debug_input(struct file *file, const char __user *user_buf,
72
                        size_t user_len, loff_t * offset);
73
static int debug_open(struct inode *inode, struct file *file);
74
static int debug_close(struct inode *inode, struct file *file);
75
static debug_info_t*  debug_info_create(char *name, int pages_per_area,
76
                        int nr_areas, int buf_size);
77
static void debug_info_get(debug_info_t *);
78
static void debug_info_put(debug_info_t *);
79
static int debug_prolog_level_fn(debug_info_t * id,
80
                        struct debug_view *view, char *out_buf);
81
static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
82
                        struct file *file, const char __user *user_buf,
83
                        size_t user_buf_size, loff_t * offset);
84
static int debug_prolog_pages_fn(debug_info_t * id,
85
                        struct debug_view *view, char *out_buf);
86
static int debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
87
                        struct file *file, const char __user *user_buf,
88
                        size_t user_buf_size, loff_t * offset);
89
static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
90
                        struct file *file, const char __user *user_buf,
91
                        size_t user_buf_size, loff_t * offset);
92
static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
93
                        char *out_buf, const char *in_buf);
94
static int debug_raw_format_fn(debug_info_t * id,
95
                        struct debug_view *view, char *out_buf,
96
                        const char *in_buf);
97
static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
98
                        int area, debug_entry_t * entry, char *out_buf);
99
 
100
static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
101
                        char *out_buf, debug_sprintf_entry_t *curr_event);
102
 
103
/* globals */
104
 
105
struct debug_view debug_raw_view = {
106
        "raw",
107
        NULL,
108
        &debug_raw_header_fn,
109
        &debug_raw_format_fn,
110
        NULL,
111
        NULL
112
};
113
 
114
struct debug_view debug_hex_ascii_view = {
115
        "hex_ascii",
116
        NULL,
117
        &debug_dflt_header_fn,
118
        &debug_hex_ascii_format_fn,
119
        NULL,
120
        NULL
121
};
122
 
123
static struct debug_view debug_level_view = {
124
        "level",
125
        &debug_prolog_level_fn,
126
        NULL,
127
        NULL,
128
        &debug_input_level_fn,
129
        NULL
130
};
131
 
132
static struct debug_view debug_pages_view = {
133
        "pages",
134
        &debug_prolog_pages_fn,
135
        NULL,
136
        NULL,
137
        &debug_input_pages_fn,
138
        NULL
139
};
140
 
141
static struct debug_view debug_flush_view = {
142
        "flush",
143
        NULL,
144
        NULL,
145
        NULL,
146
        &debug_input_flush_fn,
147
        NULL
148
};
149
 
150
struct debug_view debug_sprintf_view = {
151
        "sprintf",
152
        NULL,
153
        &debug_dflt_header_fn,
154
        (debug_format_proc_t*)&debug_sprintf_format_fn,
155
        NULL,
156
        NULL
157
};
158
 
159
/* used by dump analysis tools to determine version of debug feature */
160
unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
161
 
162
/* static globals */
163
 
164
static debug_info_t *debug_area_first = NULL;
165
static debug_info_t *debug_area_last = NULL;
166
static DEFINE_MUTEX(debug_mutex);
167
 
168
static int initialized;
169
 
170
static const struct file_operations debug_file_ops = {
171
        .owner   = THIS_MODULE,
172
        .read    = debug_output,
173
        .write   = debug_input,
174
        .open    = debug_open,
175
        .release = debug_close,
176
};
177
 
178
static struct dentry *debug_debugfs_root_entry;
179
 
180
/* functions */
181
 
182
/*
183
 * debug_areas_alloc
184
 * - Debug areas are implemented as a threedimensonal array:
185
 *   areas[areanumber][pagenumber][pageoffset]
186
 */
187
 
188
static debug_entry_t***
189
debug_areas_alloc(int pages_per_area, int nr_areas)
190
{
191
        debug_entry_t*** areas;
192
        int i,j;
193
 
194
        areas = kmalloc(nr_areas *
195
                                        sizeof(debug_entry_t**),
196
                                        GFP_KERNEL);
197
        if (!areas)
198
                goto fail_malloc_areas;
199
        for (i = 0; i < nr_areas; i++) {
200
                areas[i] = kmalloc(pages_per_area *
201
                                sizeof(debug_entry_t*),GFP_KERNEL);
202
                if (!areas[i]) {
203
                        goto fail_malloc_areas2;
204
                }
205
                for(j = 0; j < pages_per_area; j++) {
206
                        areas[i][j] = kzalloc(PAGE_SIZE, GFP_KERNEL);
207
                        if(!areas[i][j]) {
208
                                for(j--; j >=0 ; j--) {
209
                                        kfree(areas[i][j]);
210
                                }
211
                                kfree(areas[i]);
212
                                goto fail_malloc_areas2;
213
                        }
214
                }
215
        }
216
        return areas;
217
 
218
fail_malloc_areas2:
219
        for(i--; i >= 0; i--){
220
                for(j=0; j < pages_per_area;j++){
221
                        kfree(areas[i][j]);
222
                }
223
                kfree(areas[i]);
224
        }
225
        kfree(areas);
226
fail_malloc_areas:
227
        return NULL;
228
 
229
}
230
 
231
 
232
/*
233
 * debug_info_alloc
234
 * - alloc new debug-info
235
 */
236
 
237
static debug_info_t*
238
debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
239
                int level, int mode)
240
{
241
        debug_info_t* rc;
242
 
243
        /* alloc everything */
244
 
245
        rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
246
        if(!rc)
247
                goto fail_malloc_rc;
248
        rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
249
        if(!rc->active_entries)
250
                goto fail_malloc_active_entries;
251
        rc->active_pages = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
252
        if(!rc->active_pages)
253
                goto fail_malloc_active_pages;
254
        if((mode == ALL_AREAS) && (pages_per_area != 0)){
255
                rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
256
                if(!rc->areas)
257
                        goto fail_malloc_areas;
258
        } else {
259
                rc->areas = NULL;
260
        }
261
 
262
        /* initialize members */
263
 
264
        spin_lock_init(&rc->lock);
265
        rc->pages_per_area = pages_per_area;
266
        rc->nr_areas       = nr_areas;
267
        rc->active_area    = 0;
268
        rc->level          = level;
269
        rc->buf_size       = buf_size;
270
        rc->entry_size     = sizeof(debug_entry_t) + buf_size;
271
        strlcpy(rc->name, name, sizeof(rc->name));
272
        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
273
        memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
274
                sizeof(struct dentry*));
275
        atomic_set(&(rc->ref_count), 0);
276
 
277
        return rc;
278
 
279
fail_malloc_areas:
280
        kfree(rc->active_pages);
281
fail_malloc_active_pages:
282
        kfree(rc->active_entries);
283
fail_malloc_active_entries:
284
        kfree(rc);
285
fail_malloc_rc:
286
        return NULL;
287
}
288
 
289
/*
290
 * debug_areas_free
291
 * - free all debug areas
292
 */
293
 
294
static void
295
debug_areas_free(debug_info_t* db_info)
296
{
297
        int i,j;
298
 
299
        if(!db_info->areas)
300
                return;
301
        for (i = 0; i < db_info->nr_areas; i++) {
302
                for(j = 0; j < db_info->pages_per_area; j++) {
303
                        kfree(db_info->areas[i][j]);
304
                }
305
                kfree(db_info->areas[i]);
306
        }
307
        kfree(db_info->areas);
308
        db_info->areas = NULL;
309
}
310
 
311
/*
312
 * debug_info_free
313
 * - free memory debug-info
314
 */
315
 
316
static void
317
debug_info_free(debug_info_t* db_info){
318
        debug_areas_free(db_info);
319
        kfree(db_info->active_entries);
320
        kfree(db_info->active_pages);
321
        kfree(db_info);
322
}
323
 
324
/*
325
 * debug_info_create
326
 * - create new debug-info
327
 */
328
 
329
static debug_info_t*
330
debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
331
{
332
        debug_info_t* rc;
333
 
334
        rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
335
                                DEBUG_DEFAULT_LEVEL, ALL_AREAS);
336
        if(!rc)
337
                goto out;
338
 
339
        /* create root directory */
340
        rc->debugfs_root_entry = debugfs_create_dir(rc->name,
341
                                        debug_debugfs_root_entry);
342
 
343
        /* append new element to linked list */
344
        if (!debug_area_first) {
345
                /* first element in list */
346
                debug_area_first = rc;
347
                rc->prev = NULL;
348
        } else {
349
                /* append element to end of list */
350
                debug_area_last->next = rc;
351
                rc->prev = debug_area_last;
352
        }
353
        debug_area_last = rc;
354
        rc->next = NULL;
355
 
356
        debug_info_get(rc);
357
out:
358
        return rc;
359
}
360
 
361
/*
362
 * debug_info_copy
363
 * - copy debug-info
364
 */
365
 
366
static debug_info_t*
367
debug_info_copy(debug_info_t* in, int mode)
368
{
369
        int i,j;
370
        debug_info_t* rc;
371
        unsigned long flags;
372
 
373
        /* get a consistent copy of the debug areas */
374
        do {
375
                rc = debug_info_alloc(in->name, in->pages_per_area,
376
                        in->nr_areas, in->buf_size, in->level, mode);
377
                spin_lock_irqsave(&in->lock, flags);
378
                if(!rc)
379
                        goto out;
380
                /* has something changed in the meantime ? */
381
                if((rc->pages_per_area == in->pages_per_area) &&
382
                   (rc->nr_areas == in->nr_areas)) {
383
                        break;
384
                }
385
                spin_unlock_irqrestore(&in->lock, flags);
386
                debug_info_free(rc);
387
        } while (1);
388
 
389
        if(!rc || (mode == NO_AREAS))
390
                goto out;
391
 
392
        for(i = 0; i < in->nr_areas; i++){
393
                for(j = 0; j < in->pages_per_area; j++) {
394
                        memcpy(rc->areas[i][j], in->areas[i][j],PAGE_SIZE);
395
                }
396
        }
397
out:
398
        spin_unlock_irqrestore(&in->lock, flags);
399
        return rc;
400
}
401
 
402
/*
403
 * debug_info_get
404
 * - increments reference count for debug-info
405
 */
406
 
407
static void
408
debug_info_get(debug_info_t * db_info)
409
{
410
        if (db_info)
411
                atomic_inc(&db_info->ref_count);
412
}
413
 
414
/*
415
 * debug_info_put:
416
 * - decreases reference count for debug-info and frees it if necessary
417
 */
418
 
419
static void
420
debug_info_put(debug_info_t *db_info)
421
{
422
        int i;
423
 
424
        if (!db_info)
425
                return;
426
        if (atomic_dec_and_test(&db_info->ref_count)) {
427
                for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
428
                        if (!db_info->views[i])
429
                                continue;
430
                        debugfs_remove(db_info->debugfs_entries[i]);
431
                }
432
                debugfs_remove(db_info->debugfs_root_entry);
433
                if(db_info == debug_area_first)
434
                        debug_area_first = db_info->next;
435
                if(db_info == debug_area_last)
436
                        debug_area_last = db_info->prev;
437
                if(db_info->prev) db_info->prev->next = db_info->next;
438
                if(db_info->next) db_info->next->prev = db_info->prev;
439
                debug_info_free(db_info);
440
        }
441
}
442
 
443
/*
444
 * debug_format_entry:
445
 * - format one debug entry and return size of formated data
446
 */
447
 
448
static int
449
debug_format_entry(file_private_info_t *p_info)
450
{
451
        debug_info_t *id_snap   = p_info->debug_info_snap;
452
        struct debug_view *view = p_info->view;
453
        debug_entry_t *act_entry;
454
        size_t len = 0;
455
        if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
456
                /* print prolog */
457
                if (view->prolog_proc)
458
                        len += view->prolog_proc(id_snap,view,p_info->temp_buf);
459
                goto out;
460
        }
461
        if (!id_snap->areas) /* this is true, if we have a prolog only view */
462
                goto out;    /* or if 'pages_per_area' is 0 */
463
        act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area]
464
                                [p_info->act_page] + p_info->act_entry);
465
 
466
        if (act_entry->id.stck == 0LL)
467
                        goto out;  /* empty entry */
468
        if (view->header_proc)
469
                len += view->header_proc(id_snap, view, p_info->act_area,
470
                                        act_entry, p_info->temp_buf + len);
471
        if (view->format_proc)
472
                len += view->format_proc(id_snap, view, p_info->temp_buf + len,
473
                                                DEBUG_DATA(act_entry));
474
out:
475
        return len;
476
}
477
 
478
/*
479
 * debug_next_entry:
480
 * - goto next entry in p_info
481
 */
482
 
483
static inline int
484
debug_next_entry(file_private_info_t *p_info)
485
{
486
        debug_info_t *id;
487
 
488
        id = p_info->debug_info_snap;
489
        if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
490
                p_info->act_entry = 0;
491
                p_info->act_page  = 0;
492
                goto out;
493
        }
494
        if(!id->areas)
495
                return 1;
496
        p_info->act_entry += id->entry_size;
497
        /* switch to next page, if we reached the end of the page  */
498
        if (p_info->act_entry > (PAGE_SIZE - id->entry_size)){
499
                /* next page */
500
                p_info->act_entry = 0;
501
                p_info->act_page += 1;
502
                if((p_info->act_page % id->pages_per_area) == 0) {
503
                        /* next area */
504
                        p_info->act_area++;
505
                        p_info->act_page=0;
506
                }
507
                if(p_info->act_area >= id->nr_areas)
508
                        return 1;
509
        }
510
out:
511
        return 0;
512
}
513
 
514
/*
515
 * debug_output:
516
 * - called for user read()
517
 * - copies formated debug entries to the user buffer
518
 */
519
 
520
static ssize_t
521
debug_output(struct file *file,         /* file descriptor */
522
            char __user *user_buf,      /* user buffer */
523
            size_t  len,                /* length of buffer */
524
            loff_t *offset)             /* offset in the file */
525
{
526
        size_t count = 0;
527
        size_t entry_offset;
528
        file_private_info_t *p_info;
529
 
530
        p_info = ((file_private_info_t *) file->private_data);
531
        if (*offset != p_info->offset)
532
                return -EPIPE;
533
        if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
534
                return 0;
535
        entry_offset = p_info->act_entry_offset;
536
        while(count < len){
537
                int formatted_line_size;
538
                int formatted_line_residue;
539
                int user_buf_residue;
540
                size_t copy_size;
541
 
542
                formatted_line_size = debug_format_entry(p_info);
543
                formatted_line_residue = formatted_line_size - entry_offset;
544
                user_buf_residue = len-count;
545
                copy_size = min(user_buf_residue, formatted_line_residue);
546
                if(copy_size){
547
                        if (copy_to_user(user_buf + count, p_info->temp_buf
548
                                        + entry_offset, copy_size))
549
                                return -EFAULT;
550
                        count += copy_size;
551
                        entry_offset += copy_size;
552
                }
553
                if(copy_size == formatted_line_residue){
554
                        entry_offset = 0;
555
                        if(debug_next_entry(p_info))
556
                                goto out;
557
                }
558
        }
559
out:
560
        p_info->offset           = *offset + count;
561
        p_info->act_entry_offset = entry_offset;
562
        *offset = p_info->offset;
563
        return count;
564
}
565
 
566
/*
567
 * debug_input:
568
 * - called for user write()
569
 * - calls input function of view
570
 */
571
 
572
static ssize_t
573
debug_input(struct file *file, const char __user *user_buf, size_t length,
574
                loff_t *offset)
575
{
576
        int rc = 0;
577
        file_private_info_t *p_info;
578
 
579
        mutex_lock(&debug_mutex);
580
        p_info = ((file_private_info_t *) file->private_data);
581
        if (p_info->view->input_proc)
582
                rc = p_info->view->input_proc(p_info->debug_info_org,
583
                                              p_info->view, file, user_buf,
584
                                              length, offset);
585
        else
586
                rc = -EPERM;
587
        mutex_unlock(&debug_mutex);
588
        return rc;              /* number of input characters */
589
}
590
 
591
/*
592
 * debug_open:
593
 * - called for user open()
594
 * - copies formated output to private_data area of the file
595
 *   handle
596
 */
597
 
598
static int
599
debug_open(struct inode *inode, struct file *file)
600
{
601
        int i = 0, rc = 0;
602
        file_private_info_t *p_info;
603
        debug_info_t *debug_info, *debug_info_snapshot;
604
 
605
        mutex_lock(&debug_mutex);
606
        debug_info = file->f_path.dentry->d_inode->i_private;
607
        /* find debug view */
608
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
609
                if (!debug_info->views[i])
610
                        continue;
611
                else if (debug_info->debugfs_entries[i] ==
612
                         file->f_path.dentry) {
613
                        goto found;     /* found view ! */
614
                }
615
        }
616
        /* no entry found */
617
        rc = -EINVAL;
618
        goto out;
619
 
620
found:
621
 
622
        /* Make snapshot of current debug areas to get it consistent.     */
623
        /* To copy all the areas is only needed, if we have a view which  */
624
        /* formats the debug areas. */
625
 
626
        if(!debug_info->views[i]->format_proc &&
627
                !debug_info->views[i]->header_proc){
628
                debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
629
        } else {
630
                debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
631
        }
632
 
633
        if(!debug_info_snapshot){
634
                rc = -ENOMEM;
635
                goto out;
636
        }
637
        p_info = kmalloc(sizeof(file_private_info_t),
638
                                                GFP_KERNEL);
639
        if(!p_info){
640
                if(debug_info_snapshot)
641
                        debug_info_free(debug_info_snapshot);
642
                rc = -ENOMEM;
643
                goto out;
644
        }
645
        p_info->offset = 0;
646
        p_info->debug_info_snap = debug_info_snapshot;
647
        p_info->debug_info_org  = debug_info;
648
        p_info->view = debug_info->views[i];
649
        p_info->act_area = 0;
650
        p_info->act_page = 0;
651
        p_info->act_entry = DEBUG_PROLOG_ENTRY;
652
        p_info->act_entry_offset = 0;
653
        file->private_data = p_info;
654
        debug_info_get(debug_info);
655
out:
656
        mutex_unlock(&debug_mutex);
657
        return rc;
658
}
659
 
660
/*
661
 * debug_close:
662
 * - called for user close()
663
 * - deletes  private_data area of the file handle
664
 */
665
 
666
static int
667
debug_close(struct inode *inode, struct file *file)
668
{
669
        file_private_info_t *p_info;
670
        p_info = (file_private_info_t *) file->private_data;
671
        if(p_info->debug_info_snap)
672
                debug_info_free(p_info->debug_info_snap);
673
        debug_info_put(p_info->debug_info_org);
674
        kfree(file->private_data);
675
        return 0;                /* success */
676
}
677
 
678
/*
679
 * debug_register:
680
 * - creates and initializes debug area for the caller
681
 * - returns handle for debug area
682
 */
683
 
684
debug_info_t*
685
debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
686
{
687
        debug_info_t *rc = NULL;
688
 
689
        if (!initialized)
690
                BUG();
691
        mutex_lock(&debug_mutex);
692
 
693
        /* create new debug_info */
694
 
695
        rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
696
        if(!rc)
697
                goto out;
698
        debug_register_view(rc, &debug_level_view);
699
        debug_register_view(rc, &debug_flush_view);
700
        debug_register_view(rc, &debug_pages_view);
701
out:
702
        if (!rc){
703
                printk(KERN_ERR "debug: debug_register failed for %s\n",name);
704
        }
705
        mutex_unlock(&debug_mutex);
706
        return rc;
707
}
708
 
709
/*
710
 * debug_unregister:
711
 * - give back debug area
712
 */
713
 
714
void
715
debug_unregister(debug_info_t * id)
716
{
717
        if (!id)
718
                goto out;
719
        mutex_lock(&debug_mutex);
720
        debug_info_put(id);
721
        mutex_unlock(&debug_mutex);
722
 
723
out:
724
        return;
725
}
726
 
727
/*
728
 * debug_set_size:
729
 * - set area size (number of pages) and number of areas
730
 */
731
static int
732
debug_set_size(debug_info_t* id, int nr_areas, int pages_per_area)
733
{
734
        unsigned long flags;
735
        debug_entry_t *** new_areas;
736
        int rc=0;
737
 
738
        if(!id || (nr_areas <= 0) || (pages_per_area < 0))
739
                return -EINVAL;
740
        if(pages_per_area > 0){
741
                new_areas = debug_areas_alloc(pages_per_area, nr_areas);
742
                if(!new_areas) {
743
                        printk(KERN_WARNING "debug: could not allocate memory "\
744
                                         "for pagenumber: %i\n",pages_per_area);
745
                        rc = -ENOMEM;
746
                        goto out;
747
                }
748
        } else {
749
                new_areas = NULL;
750
        }
751
        spin_lock_irqsave(&id->lock,flags);
752
        debug_areas_free(id);
753
        id->areas = new_areas;
754
        id->nr_areas = nr_areas;
755
        id->pages_per_area = pages_per_area;
756
        id->active_area = 0;
757
        memset(id->active_entries,0,sizeof(int)*id->nr_areas);
758
        memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
759
        spin_unlock_irqrestore(&id->lock,flags);
760
        printk(KERN_INFO "debug: %s: set new size (%i pages)\n"\
761
                         ,id->name, pages_per_area);
762
out:
763
        return rc;
764
}
765
 
766
/*
767
 * debug_set_level:
768
 * - set actual debug level
769
 */
770
 
771
void
772
debug_set_level(debug_info_t* id, int new_level)
773
{
774
        unsigned long flags;
775
        if(!id)
776
                return;
777
        spin_lock_irqsave(&id->lock,flags);
778
        if(new_level == DEBUG_OFF_LEVEL){
779
                id->level = DEBUG_OFF_LEVEL;
780
                printk(KERN_INFO "debug: %s: switched off\n",id->name);
781
        } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
782
                printk(KERN_INFO
783
                        "debug: %s: level %i is out of range (%i - %i)\n",
784
                        id->name, new_level, 0, DEBUG_MAX_LEVEL);
785
        } else {
786
                id->level = new_level;
787
        }
788
        spin_unlock_irqrestore(&id->lock,flags);
789
}
790
 
791
 
792
/*
793
 * proceed_active_entry:
794
 * - set active entry to next in the ring buffer
795
 */
796
 
797
static inline void
798
proceed_active_entry(debug_info_t * id)
799
{
800
        if ((id->active_entries[id->active_area] += id->entry_size)
801
            > (PAGE_SIZE - id->entry_size)){
802
                id->active_entries[id->active_area] = 0;
803
                id->active_pages[id->active_area] =
804
                        (id->active_pages[id->active_area] + 1) %
805
                        id->pages_per_area;
806
        }
807
}
808
 
809
/*
810
 * proceed_active_area:
811
 * - set active area to next in the ring buffer
812
 */
813
 
814
static inline void
815
proceed_active_area(debug_info_t * id)
816
{
817
        id->active_area++;
818
        id->active_area = id->active_area % id->nr_areas;
819
}
820
 
821
/*
822
 * get_active_entry:
823
 */
824
 
825
static inline debug_entry_t*
826
get_active_entry(debug_info_t * id)
827
{
828
        return (debug_entry_t *) (((char *) id->areas[id->active_area]
829
                                        [id->active_pages[id->active_area]]) +
830
                                        id->active_entries[id->active_area]);
831
}
832
 
833
/*
834
 * debug_finish_entry:
835
 * - set timestamp, caller address, cpu number etc.
836
 */
837
 
838
static inline void
839
debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
840
                        int exception)
841
{
842
        active->id.stck = get_clock();
843
        active->id.fields.cpuid = smp_processor_id();
844
        active->caller = __builtin_return_address(0);
845
        active->id.fields.exception = exception;
846
        active->id.fields.level     = level;
847
        proceed_active_entry(id);
848
        if(exception)
849
                proceed_active_area(id);
850
}
851
 
852
static int debug_stoppable=1;
853
static int debug_active=1;
854
 
855
#define CTL_S390DBF_STOPPABLE 5678
856
#define CTL_S390DBF_ACTIVE 5679
857
 
858
/*
859
 * proc handler for the running debug_active sysctl
860
 * always allow read, allow write only if debug_stoppable is set or
861
 * if debug_active is already off
862
 */
863
static int
864
s390dbf_procactive(ctl_table *table, int write, struct file *filp,
865
                     void __user *buffer, size_t *lenp, loff_t *ppos)
866
{
867
        if (!write || debug_stoppable || !debug_active)
868
                return proc_dointvec(table, write, filp, buffer, lenp, ppos);
869
        else
870
                return 0;
871
}
872
 
873
 
874
static struct ctl_table s390dbf_table[] = {
875
        {
876
                .ctl_name       = CTL_S390DBF_STOPPABLE,
877
                .procname       = "debug_stoppable",
878
                .data           = &debug_stoppable,
879
                .maxlen         = sizeof(int),
880
                .mode           = S_IRUGO | S_IWUSR,
881
                .proc_handler   = &proc_dointvec,
882
                .strategy       = &sysctl_intvec,
883
        },
884
         {
885
                .ctl_name       = CTL_S390DBF_ACTIVE,
886
                .procname       = "debug_active",
887
                .data           = &debug_active,
888
                .maxlen         = sizeof(int),
889
                .mode           = S_IRUGO | S_IWUSR,
890
                .proc_handler   = &s390dbf_procactive,
891
                .strategy       = &sysctl_intvec,
892
        },
893
        { .ctl_name = 0 }
894
};
895
 
896
static struct ctl_table s390dbf_dir_table[] = {
897
        {
898
                .ctl_name       = CTL_S390DBF,
899
                .procname       = "s390dbf",
900
                .maxlen         = 0,
901
                .mode           = S_IRUGO | S_IXUGO,
902
                .child          = s390dbf_table,
903
        },
904
        { .ctl_name = 0 }
905
};
906
 
907
static struct ctl_table_header *s390dbf_sysctl_header;
908
 
909
void
910
debug_stop_all(void)
911
{
912
        if (debug_stoppable)
913
                debug_active = 0;
914
}
915
 
916
 
917
/*
918
 * debug_event_common:
919
 * - write debug entry with given size
920
 */
921
 
922
debug_entry_t*
923
debug_event_common(debug_info_t * id, int level, const void *buf, int len)
924
{
925
        unsigned long flags;
926
        debug_entry_t *active;
927
 
928
        if (!debug_active || !id->areas)
929
                return NULL;
930
        spin_lock_irqsave(&id->lock, flags);
931
        active = get_active_entry(id);
932
        memset(DEBUG_DATA(active), 0, id->buf_size);
933
        memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
934
        debug_finish_entry(id, active, level, 0);
935
        spin_unlock_irqrestore(&id->lock, flags);
936
 
937
        return active;
938
}
939
 
940
/*
941
 * debug_exception_common:
942
 * - write debug entry with given size and switch to next debug area
943
 */
944
 
945
debug_entry_t
946
*debug_exception_common(debug_info_t * id, int level, const void *buf, int len)
947
{
948
        unsigned long flags;
949
        debug_entry_t *active;
950
 
951
        if (!debug_active || !id->areas)
952
                return NULL;
953
        spin_lock_irqsave(&id->lock, flags);
954
        active = get_active_entry(id);
955
        memset(DEBUG_DATA(active), 0, id->buf_size);
956
        memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
957
        debug_finish_entry(id, active, level, 1);
958
        spin_unlock_irqrestore(&id->lock, flags);
959
 
960
        return active;
961
}
962
 
963
/*
964
 * counts arguments in format string for sprintf view
965
 */
966
 
967
static inline int
968
debug_count_numargs(char *string)
969
{
970
        int numargs=0;
971
 
972
        while(*string) {
973
                if(*string++=='%')
974
                        numargs++;
975
        }
976
        return(numargs);
977
}
978
 
979
/*
980
 * debug_sprintf_event:
981
 */
982
 
983
debug_entry_t*
984
debug_sprintf_event(debug_info_t* id, int level,char *string,...)
985
{
986
        va_list   ap;
987
        int numargs,idx;
988
        unsigned long flags;
989
        debug_sprintf_entry_t *curr_event;
990
        debug_entry_t *active;
991
 
992
        if((!id) || (level > id->level))
993
                return NULL;
994
        if (!debug_active || !id->areas)
995
                return NULL;
996
        numargs=debug_count_numargs(string);
997
 
998
        spin_lock_irqsave(&id->lock, flags);
999
        active = get_active_entry(id);
1000
        curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
1001
        va_start(ap,string);
1002
        curr_event->string=string;
1003
        for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
1004
                curr_event->args[idx]=va_arg(ap,long);
1005
        va_end(ap);
1006
        debug_finish_entry(id, active, level, 0);
1007
        spin_unlock_irqrestore(&id->lock, flags);
1008
 
1009
        return active;
1010
}
1011
 
1012
/*
1013
 * debug_sprintf_exception:
1014
 */
1015
 
1016
debug_entry_t*
1017
debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
1018
{
1019
        va_list   ap;
1020
        int numargs,idx;
1021
        unsigned long flags;
1022
        debug_sprintf_entry_t *curr_event;
1023
        debug_entry_t *active;
1024
 
1025
        if((!id) || (level > id->level))
1026
                return NULL;
1027
        if (!debug_active || !id->areas)
1028
                return NULL;
1029
 
1030
        numargs=debug_count_numargs(string);
1031
 
1032
        spin_lock_irqsave(&id->lock, flags);
1033
        active = get_active_entry(id);
1034
        curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
1035
        va_start(ap,string);
1036
        curr_event->string=string;
1037
        for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
1038
                curr_event->args[idx]=va_arg(ap,long);
1039
        va_end(ap);
1040
        debug_finish_entry(id, active, level, 1);
1041
        spin_unlock_irqrestore(&id->lock, flags);
1042
 
1043
        return active;
1044
}
1045
 
1046
/*
1047
 * debug_init:
1048
 * - is called exactly once to initialize the debug feature
1049
 */
1050
 
1051
static int
1052
__init debug_init(void)
1053
{
1054
        int rc = 0;
1055
 
1056
        s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
1057
        mutex_lock(&debug_mutex);
1058
        debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
1059
        printk(KERN_INFO "debug: Initialization complete\n");
1060
        initialized = 1;
1061
        mutex_unlock(&debug_mutex);
1062
 
1063
        return rc;
1064
}
1065
 
1066
/*
1067
 * debug_register_view:
1068
 */
1069
 
1070
int
1071
debug_register_view(debug_info_t * id, struct debug_view *view)
1072
{
1073
        int rc = 0;
1074
        int i;
1075
        unsigned long flags;
1076
        mode_t mode = S_IFREG;
1077
        struct dentry *pde;
1078
 
1079
        if (!id)
1080
                goto out;
1081
        if (view->prolog_proc || view->format_proc || view->header_proc)
1082
                mode |= S_IRUSR;
1083
        if (view->input_proc)
1084
                mode |= S_IWUSR;
1085
        pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
1086
                                id , &debug_file_ops);
1087
        if (!pde){
1088
                printk(KERN_WARNING "debug: debugfs_create_file() failed!"\
1089
                        " Cannot register view %s/%s\n", id->name,view->name);
1090
                rc = -1;
1091
                goto out;
1092
        }
1093
        spin_lock_irqsave(&id->lock, flags);
1094
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
1095
                if (!id->views[i])
1096
                        break;
1097
        }
1098
        if (i == DEBUG_MAX_VIEWS) {
1099
                printk(KERN_WARNING "debug: cannot register view %s/%s\n",
1100
                        id->name,view->name);
1101
                printk(KERN_WARNING
1102
                        "debug: maximum number of views reached (%i)!\n", i);
1103
                debugfs_remove(pde);
1104
                rc = -1;
1105
        } else {
1106
                id->views[i] = view;
1107
                id->debugfs_entries[i] = pde;
1108
        }
1109
        spin_unlock_irqrestore(&id->lock, flags);
1110
out:
1111
        return rc;
1112
}
1113
 
1114
/*
1115
 * debug_unregister_view:
1116
 */
1117
 
1118
int
1119
debug_unregister_view(debug_info_t * id, struct debug_view *view)
1120
{
1121
        int rc = 0;
1122
        int i;
1123
        unsigned long flags;
1124
 
1125
        if (!id)
1126
                goto out;
1127
        spin_lock_irqsave(&id->lock, flags);
1128
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
1129
                if (id->views[i] == view)
1130
                        break;
1131
        }
1132
        if (i == DEBUG_MAX_VIEWS)
1133
                rc = -1;
1134
        else {
1135
                debugfs_remove(id->debugfs_entries[i]);
1136
                id->views[i] = NULL;
1137
                rc = 0;
1138
        }
1139
        spin_unlock_irqrestore(&id->lock, flags);
1140
out:
1141
        return rc;
1142
}
1143
 
1144
static inline char *
1145
debug_get_user_string(const char __user *user_buf, size_t user_len)
1146
{
1147
        char* buffer;
1148
 
1149
        buffer = kmalloc(user_len + 1, GFP_KERNEL);
1150
        if (!buffer)
1151
                return ERR_PTR(-ENOMEM);
1152
        if (copy_from_user(buffer, user_buf, user_len) != 0) {
1153
                kfree(buffer);
1154
                return ERR_PTR(-EFAULT);
1155
        }
1156
        /* got the string, now strip linefeed. */
1157
        if (buffer[user_len - 1] == '\n')
1158
                buffer[user_len - 1] = 0;
1159
        else
1160
                buffer[user_len] = 0;
1161
        return buffer;
1162
}
1163
 
1164
static inline int
1165
debug_get_uint(char *buf)
1166
{
1167
        int rc;
1168
 
1169
        for(; isspace(*buf); buf++);
1170
        rc = simple_strtoul(buf, &buf, 10);
1171
        if(*buf){
1172
                printk("debug: no integer specified!\n");
1173
                rc = -EINVAL;
1174
        }
1175
        return rc;
1176
}
1177
 
1178
/*
1179
 * functions for debug-views
1180
 ***********************************
1181
*/
1182
 
1183
/*
1184
 * prints out actual debug level
1185
 */
1186
 
1187
static int
1188
debug_prolog_pages_fn(debug_info_t * id,
1189
                                 struct debug_view *view, char *out_buf)
1190
{
1191
        return sprintf(out_buf, "%i\n", id->pages_per_area);
1192
}
1193
 
1194
/*
1195
 * reads new size (number of pages per debug area)
1196
 */
1197
 
1198
static int
1199
debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
1200
                        struct file *file, const char __user *user_buf,
1201
                        size_t user_len, loff_t * offset)
1202
{
1203
        char *str;
1204
        int rc,new_pages;
1205
 
1206
        if (user_len > 0x10000)
1207
                user_len = 0x10000;
1208
        if (*offset != 0){
1209
                rc = -EPIPE;
1210
                goto out;
1211
        }
1212
        str = debug_get_user_string(user_buf,user_len);
1213
        if(IS_ERR(str)){
1214
                rc = PTR_ERR(str);
1215
                goto out;
1216
        }
1217
        new_pages = debug_get_uint(str);
1218
        if(new_pages < 0){
1219
                rc = -EINVAL;
1220
                goto free_str;
1221
        }
1222
        rc = debug_set_size(id,id->nr_areas, new_pages);
1223
        if(rc != 0){
1224
                rc = -EINVAL;
1225
                goto free_str;
1226
        }
1227
        rc = user_len;
1228
free_str:
1229
        kfree(str);
1230
out:
1231
        *offset += user_len;
1232
        return rc;              /* number of input characters */
1233
}
1234
 
1235
/*
1236
 * prints out actual debug level
1237
 */
1238
 
1239
static int
1240
debug_prolog_level_fn(debug_info_t * id, struct debug_view *view, char *out_buf)
1241
{
1242
        int rc = 0;
1243
 
1244
        if(id->level == DEBUG_OFF_LEVEL) {
1245
                rc = sprintf(out_buf,"-\n");
1246
        }
1247
        else {
1248
                rc = sprintf(out_buf, "%i\n", id->level);
1249
        }
1250
        return rc;
1251
}
1252
 
1253
/*
1254
 * reads new debug level
1255
 */
1256
 
1257
static int
1258
debug_input_level_fn(debug_info_t * id, struct debug_view *view,
1259
                        struct file *file, const char __user *user_buf,
1260
                        size_t user_len, loff_t * offset)
1261
{
1262
        char *str;
1263
        int rc,new_level;
1264
 
1265
        if (user_len > 0x10000)
1266
                user_len = 0x10000;
1267
        if (*offset != 0){
1268
                rc = -EPIPE;
1269
                goto out;
1270
        }
1271
        str = debug_get_user_string(user_buf,user_len);
1272
        if(IS_ERR(str)){
1273
                rc = PTR_ERR(str);
1274
                goto out;
1275
        }
1276
        if(str[0] == '-'){
1277
                debug_set_level(id, DEBUG_OFF_LEVEL);
1278
                rc = user_len;
1279
                goto free_str;
1280
        } else {
1281
                new_level = debug_get_uint(str);
1282
        }
1283
        if(new_level < 0) {
1284
                printk(KERN_INFO "debug: level `%s` is not valid\n", str);
1285
                rc = -EINVAL;
1286
        } else {
1287
                debug_set_level(id, new_level);
1288
                rc = user_len;
1289
        }
1290
free_str:
1291
        kfree(str);
1292
out:
1293
        *offset += user_len;
1294
        return rc;              /* number of input characters */
1295
}
1296
 
1297
 
1298
/*
1299
 * flushes debug areas
1300
 */
1301
 
1302
static void debug_flush(debug_info_t* id, int area)
1303
{
1304
        unsigned long flags;
1305
        int i,j;
1306
 
1307
        if(!id || !id->areas)
1308
                return;
1309
        spin_lock_irqsave(&id->lock,flags);
1310
        if(area == DEBUG_FLUSH_ALL){
1311
                id->active_area = 0;
1312
                memset(id->active_entries, 0, id->nr_areas * sizeof(int));
1313
                for (i = 0; i < id->nr_areas; i++) {
1314
                        id->active_pages[i] = 0;
1315
                        for(j = 0; j < id->pages_per_area; j++) {
1316
                                memset(id->areas[i][j], 0, PAGE_SIZE);
1317
                        }
1318
                }
1319
                printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
1320
        } else if(area >= 0 && area < id->nr_areas) {
1321
                id->active_entries[area] = 0;
1322
                id->active_pages[area] = 0;
1323
                for(i = 0; i < id->pages_per_area; i++) {
1324
                        memset(id->areas[area][i],0,PAGE_SIZE);
1325
                }
1326
                printk(KERN_INFO "debug: %s: area %i has been flushed\n",
1327
                        id->name, area);
1328
        } else {
1329
                printk(KERN_INFO
1330
                      "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
1331
                        id->name, area, 0, id->nr_areas-1);
1332
        }
1333
        spin_unlock_irqrestore(&id->lock,flags);
1334
}
1335
 
1336
/*
1337
 * view function: flushes debug areas
1338
 */
1339
 
1340
static int
1341
debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1342
                        struct file *file, const char __user *user_buf,
1343
                        size_t user_len, loff_t * offset)
1344
{
1345
        char input_buf[1];
1346
        int rc = user_len;
1347
 
1348
        if (user_len > 0x10000)
1349
                user_len = 0x10000;
1350
        if (*offset != 0){
1351
                rc = -EPIPE;
1352
                goto out;
1353
        }
1354
        if (copy_from_user(input_buf, user_buf, 1)){
1355
                rc = -EFAULT;
1356
                goto out;
1357
        }
1358
        if(input_buf[0] == '-') {
1359
                debug_flush(id, DEBUG_FLUSH_ALL);
1360
                goto out;
1361
        }
1362
        if (isdigit(input_buf[0])) {
1363
                int area = ((int) input_buf[0] - (int) '0');
1364
                debug_flush(id, area);
1365
                goto out;
1366
        }
1367
 
1368
        printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
1369
 
1370
out:
1371
        *offset += user_len;
1372
        return rc;              /* number of input characters */
1373
}
1374
 
1375
/*
1376
 * prints debug header in raw format
1377
 */
1378
 
1379
static int
1380
debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1381
                        int area, debug_entry_t * entry, char *out_buf)
1382
{
1383
        int rc;
1384
 
1385
        rc = sizeof(debug_entry_t);
1386
        memcpy(out_buf,entry,sizeof(debug_entry_t));
1387
        return rc;
1388
}
1389
 
1390
/*
1391
 * prints debug data in raw format
1392
 */
1393
 
1394
static int
1395
debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1396
                               char *out_buf, const char *in_buf)
1397
{
1398
        int rc;
1399
 
1400
        rc = id->buf_size;
1401
        memcpy(out_buf, in_buf, id->buf_size);
1402
        return rc;
1403
}
1404
 
1405
/*
1406
 * prints debug data in hex/ascii format
1407
 */
1408
 
1409
static int
1410
debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1411
                          char *out_buf, const char *in_buf)
1412
{
1413
        int i, rc = 0;
1414
 
1415
        for (i = 0; i < id->buf_size; i++) {
1416
                rc += sprintf(out_buf + rc, "%02x ",
1417
                              ((unsigned char *) in_buf)[i]);
1418
        }
1419
        rc += sprintf(out_buf + rc, "| ");
1420
        for (i = 0; i < id->buf_size; i++) {
1421
                unsigned char c = in_buf[i];
1422
                if (!isprint(c))
1423
                        rc += sprintf(out_buf + rc, ".");
1424
                else
1425
                        rc += sprintf(out_buf + rc, "%c", c);
1426
        }
1427
        rc += sprintf(out_buf + rc, "\n");
1428
        return rc;
1429
}
1430
 
1431
/*
1432
 * prints header for debug entry
1433
 */
1434
 
1435
int
1436
debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1437
                         int area, debug_entry_t * entry, char *out_buf)
1438
{
1439
        struct timespec time_spec;
1440
        unsigned long long time;
1441
        char *except_str;
1442
        unsigned long caller;
1443
        int rc = 0;
1444
        unsigned int level;
1445
 
1446
        level = entry->id.fields.level;
1447
        time = entry->id.stck;
1448
        /* adjust todclock to 1970 */
1449
        time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
1450
        tod_to_timeval(time, &time_spec);
1451
 
1452
        if (entry->id.fields.exception)
1453
                except_str = "*";
1454
        else
1455
                except_str = "-";
1456
        caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN;
1457
        rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p  ",
1458
                      area, time_spec.tv_sec, time_spec.tv_nsec / 1000, level,
1459
                      except_str, entry->id.fields.cpuid, (void *) caller);
1460
        return rc;
1461
}
1462
 
1463
/*
1464
 * prints debug data sprintf-formated:
1465
 * debug_sprinf_event/exception calls must be used together with this view
1466
 */
1467
 
1468
#define DEBUG_SPRINTF_MAX_ARGS 10
1469
 
1470
static int
1471
debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
1472
                        char *out_buf, debug_sprintf_entry_t *curr_event)
1473
{
1474
        int num_longs, num_used_args = 0,i, rc = 0;
1475
        int index[DEBUG_SPRINTF_MAX_ARGS];
1476
 
1477
        /* count of longs fit into one entry */
1478
        num_longs = id->buf_size /  sizeof(long);
1479
 
1480
        if(num_longs < 1)
1481
                goto out; /* bufsize of entry too small */
1482
        if(num_longs == 1) {
1483
                /* no args, we use only the string */
1484
                strcpy(out_buf, curr_event->string);
1485
                rc = strlen(curr_event->string);
1486
                goto out;
1487
        }
1488
 
1489
        /* number of arguments used for sprintf (without the format string) */
1490
        num_used_args   = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
1491
 
1492
        memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
1493
 
1494
        for(i = 0; i < num_used_args; i++)
1495
                index[i] = i;
1496
 
1497
        rc =  sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
1498
                curr_event->args[index[1]], curr_event->args[index[2]],
1499
                curr_event->args[index[3]], curr_event->args[index[4]],
1500
                curr_event->args[index[5]], curr_event->args[index[6]],
1501
                curr_event->args[index[7]], curr_event->args[index[8]],
1502
                curr_event->args[index[9]]);
1503
 
1504
out:
1505
 
1506
        return rc;
1507
}
1508
 
1509
/*
1510
 * clean up module
1511
 */
1512
static void __exit debug_exit(void)
1513
{
1514
        debugfs_remove(debug_debugfs_root_entry);
1515
        unregister_sysctl_table(s390dbf_sysctl_header);
1516
        return;
1517
}
1518
 
1519
/*
1520
 * module definitions
1521
 */
1522
postcore_initcall(debug_init);
1523
module_exit(debug_exit);
1524
MODULE_LICENSE("GPL");
1525
 
1526
EXPORT_SYMBOL(debug_register);
1527
EXPORT_SYMBOL(debug_unregister);
1528
EXPORT_SYMBOL(debug_set_level);
1529
EXPORT_SYMBOL(debug_stop_all);
1530
EXPORT_SYMBOL(debug_register_view);
1531
EXPORT_SYMBOL(debug_unregister_view);
1532
EXPORT_SYMBOL(debug_event_common);
1533
EXPORT_SYMBOL(debug_exception_common);
1534
EXPORT_SYMBOL(debug_hex_ascii_view);
1535
EXPORT_SYMBOL(debug_raw_view);
1536
EXPORT_SYMBOL(debug_dflt_header_fn);
1537
EXPORT_SYMBOL(debug_sprintf_view);
1538
EXPORT_SYMBOL(debug_sprintf_exception);
1539
EXPORT_SYMBOL(debug_sprintf_event);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.