Merge tag 'staging-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-microblaze.git] / drivers / isdn / capi / kcapi_proc.c
1 /*
2  * Kernel CAPI 2.0 Module - /proc/capi handling
3  *
4  * Copyright 1999 by Carsten Paeth <calle@calle.de>
5  * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
6  *
7  * This software may be used and distributed according to the terms
8  * of the GNU General Public License, incorporated herein by reference.
9  *
10  */
11
12
13 #include "kcapi.h"
14 #include <linux/proc_fs.h>
15 #include <linux/seq_file.h>
16 #include <linux/init.h>
17 #include <linux/export.h>
18
19 static char *state2str(unsigned short state)
20 {
21         switch (state) {
22         case CAPI_CTR_DETECTED: return "detected";
23         case CAPI_CTR_LOADING:  return "loading";
24         case CAPI_CTR_RUNNING:  return "running";
25         default:                return "???";
26         }
27 }
28
29 // /proc/capi
30 // ===========================================================================
31
32 // /proc/capi/controller:
33 //      cnr driver cardstate name driverinfo
34 // /proc/capi/contrstats:
35 //      cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
36 // ---------------------------------------------------------------------------
37
38 static void *controller_start(struct seq_file *seq, loff_t *pos)
39         __acquires(capi_controller_lock)
40 {
41         mutex_lock(&capi_controller_lock);
42
43         if (*pos < CAPI_MAXCONTR)
44                 return &capi_controller[*pos];
45
46         return NULL;
47 }
48
49 static void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
50 {
51         ++*pos;
52         if (*pos < CAPI_MAXCONTR)
53                 return &capi_controller[*pos];
54
55         return NULL;
56 }
57
58 static void controller_stop(struct seq_file *seq, void *v)
59         __releases(capi_controller_lock)
60 {
61         mutex_unlock(&capi_controller_lock);
62 }
63
64 static int controller_show(struct seq_file *seq, void *v)
65 {
66         struct capi_ctr *ctr = *(struct capi_ctr **) v;
67
68         if (!ctr)
69                 return 0;
70
71         seq_printf(seq, "%d %-10s %-8s %-16s %s\n",
72                    ctr->cnr, ctr->driver_name,
73                    state2str(ctr->state),
74                    ctr->name,
75                    ctr->procinfo ?  ctr->procinfo(ctr) : "");
76
77         return 0;
78 }
79
80 static int contrstats_show(struct seq_file *seq, void *v)
81 {
82         struct capi_ctr *ctr = *(struct capi_ctr **) v;
83
84         if (!ctr)
85                 return 0;
86
87         seq_printf(seq, "%d %lu %lu %lu %lu\n",
88                    ctr->cnr,
89                    ctr->nrecvctlpkt,
90                    ctr->nrecvdatapkt,
91                    ctr->nsentctlpkt,
92                    ctr->nsentdatapkt);
93
94         return 0;
95 }
96
97 static const struct seq_operations seq_controller_ops = {
98         .start  = controller_start,
99         .next   = controller_next,
100         .stop   = controller_stop,
101         .show   = controller_show,
102 };
103
104 static const struct seq_operations seq_contrstats_ops = {
105         .start  = controller_start,
106         .next   = controller_next,
107         .stop   = controller_stop,
108         .show   = contrstats_show,
109 };
110
111 // /proc/capi/applications:
112 //      applid l3cnt dblkcnt dblklen #ncci recvqueuelen
113 // /proc/capi/applstats:
114 //      applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
115 // ---------------------------------------------------------------------------
116
117 static void *applications_start(struct seq_file *seq, loff_t *pos)
118         __acquires(capi_controller_lock)
119 {
120         mutex_lock(&capi_controller_lock);
121
122         if (*pos < CAPI_MAXAPPL)
123                 return &capi_applications[*pos];
124
125         return NULL;
126 }
127
128 static void *
129 applications_next(struct seq_file *seq, void *v, loff_t *pos)
130 {
131         ++*pos;
132         if (*pos < CAPI_MAXAPPL)
133                 return &capi_applications[*pos];
134
135         return NULL;
136 }
137
138 static void applications_stop(struct seq_file *seq, void *v)
139         __releases(capi_controller_lock)
140 {
141         mutex_unlock(&capi_controller_lock);
142 }
143
144 static int
145 applications_show(struct seq_file *seq, void *v)
146 {
147         struct capi20_appl *ap = *(struct capi20_appl **) v;
148
149         if (!ap)
150                 return 0;
151
152         seq_printf(seq, "%u %d %d %d\n",
153                    ap->applid,
154                    ap->rparam.level3cnt,
155                    ap->rparam.datablkcnt,
156                    ap->rparam.datablklen);
157
158         return 0;
159 }
160
161 static int
162 applstats_show(struct seq_file *seq, void *v)
163 {
164         struct capi20_appl *ap = *(struct capi20_appl **) v;
165
166         if (!ap)
167                 return 0;
168
169         seq_printf(seq, "%u %lu %lu %lu %lu\n",
170                    ap->applid,
171                    ap->nrecvctlpkt,
172                    ap->nrecvdatapkt,
173                    ap->nsentctlpkt,
174                    ap->nsentdatapkt);
175
176         return 0;
177 }
178
179 static const struct seq_operations seq_applications_ops = {
180         .start  = applications_start,
181         .next   = applications_next,
182         .stop   = applications_stop,
183         .show   = applications_show,
184 };
185
186 static const struct seq_operations seq_applstats_ops = {
187         .start  = applications_start,
188         .next   = applications_next,
189         .stop   = applications_stop,
190         .show   = applstats_show,
191 };
192
193 // ---------------------------------------------------------------------------
194
195 /* /proc/capi/drivers is always empty */
196 static ssize_t empty_read(struct file *file, char __user *buf,
197                           size_t size, loff_t *off)
198 {
199         return 0;
200 }
201
202 static const struct file_operations empty_fops = {
203         .read   = empty_read,
204 };
205
206 // ---------------------------------------------------------------------------
207
208 void __init
209 kcapi_proc_init(void)
210 {
211         proc_mkdir("capi",             NULL);
212         proc_mkdir("capi/controllers", NULL);
213         proc_create_seq("capi/controller",   0, NULL, &seq_controller_ops);
214         proc_create_seq("capi/contrstats",   0, NULL, &seq_contrstats_ops);
215         proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops);
216         proc_create_seq("capi/applstats",    0, NULL, &seq_applstats_ops);
217         proc_create("capi/driver",           0, NULL, &empty_fops);
218 }
219
220 void
221 kcapi_proc_exit(void)
222 {
223         remove_proc_entry("capi/driver",       NULL);
224         remove_proc_entry("capi/controller",   NULL);
225         remove_proc_entry("capi/contrstats",   NULL);
226         remove_proc_entry("capi/applications", NULL);
227         remove_proc_entry("capi/applstats",    NULL);
228         remove_proc_entry("capi/controllers",  NULL);
229         remove_proc_entry("capi",              NULL);
230 }