Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / net / atm / resources.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* net/atm/resources.c - Statically allocated resources */
3
4 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
5
6 /* Fixes
7  * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
8  * 2002/01 - don't free the whole struct sock on sk->destruct time,
9  *           use the default destruct function initialized by sock_init_data */
10
11 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
12
13 #include <linux/ctype.h>
14 #include <linux/string.h>
15 #include <linux/atmdev.h>
16 #include <linux/sonet.h>
17 #include <linux/kernel.h> /* for barrier */
18 #include <linux/module.h>
19 #include <linux/bitops.h>
20 #include <linux/capability.h>
21 #include <linux/delay.h>
22 #include <linux/mutex.h>
23 #include <linux/slab.h>
24
25 #include <net/sock.h>    /* for struct sock */
26
27 #include "common.h"
28 #include "resources.h"
29 #include "addr.h"
30
31
32 LIST_HEAD(atm_devs);
33 DEFINE_MUTEX(atm_dev_mutex);
34
35 static struct atm_dev *__alloc_atm_dev(const char *type)
36 {
37         struct atm_dev *dev;
38
39         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
40         if (!dev)
41                 return NULL;
42         dev->type = type;
43         dev->signal = ATM_PHY_SIG_UNKNOWN;
44         dev->link_rate = ATM_OC3_PCR;
45         spin_lock_init(&dev->lock);
46         INIT_LIST_HEAD(&dev->local);
47         INIT_LIST_HEAD(&dev->lecs);
48
49         return dev;
50 }
51
52 static struct atm_dev *__atm_dev_lookup(int number)
53 {
54         struct atm_dev *dev;
55         struct list_head *p;
56
57         list_for_each(p, &atm_devs) {
58                 dev = list_entry(p, struct atm_dev, dev_list);
59                 if (dev->number == number) {
60                         atm_dev_hold(dev);
61                         return dev;
62                 }
63         }
64         return NULL;
65 }
66
67 struct atm_dev *atm_dev_lookup(int number)
68 {
69         struct atm_dev *dev;
70
71         mutex_lock(&atm_dev_mutex);
72         dev = __atm_dev_lookup(number);
73         mutex_unlock(&atm_dev_mutex);
74         return dev;
75 }
76 EXPORT_SYMBOL(atm_dev_lookup);
77
78 struct atm_dev *atm_dev_register(const char *type, struct device *parent,
79                                  const struct atmdev_ops *ops, int number,
80                                  unsigned long *flags)
81 {
82         struct atm_dev *dev, *inuse;
83
84         dev = __alloc_atm_dev(type);
85         if (!dev) {
86                 pr_err("no space for dev %s\n", type);
87                 return NULL;
88         }
89         mutex_lock(&atm_dev_mutex);
90         if (number != -1) {
91                 inuse = __atm_dev_lookup(number);
92                 if (inuse) {
93                         atm_dev_put(inuse);
94                         mutex_unlock(&atm_dev_mutex);
95                         kfree(dev);
96                         return NULL;
97                 }
98                 dev->number = number;
99         } else {
100                 dev->number = 0;
101                 while ((inuse = __atm_dev_lookup(dev->number))) {
102                         atm_dev_put(inuse);
103                         dev->number++;
104                 }
105         }
106
107         dev->ops = ops;
108         if (flags)
109                 dev->flags = *flags;
110         else
111                 memset(&dev->flags, 0, sizeof(dev->flags));
112         memset(&dev->stats, 0, sizeof(dev->stats));
113         refcount_set(&dev->refcnt, 1);
114
115         if (atm_proc_dev_register(dev) < 0) {
116                 pr_err("atm_proc_dev_register failed for dev %s\n", type);
117                 goto out_fail;
118         }
119
120         if (atm_register_sysfs(dev, parent) < 0) {
121                 pr_err("atm_register_sysfs failed for dev %s\n", type);
122                 atm_proc_dev_deregister(dev);
123                 goto out_fail;
124         }
125
126         list_add_tail(&dev->dev_list, &atm_devs);
127
128 out:
129         mutex_unlock(&atm_dev_mutex);
130         return dev;
131
132 out_fail:
133         kfree(dev);
134         dev = NULL;
135         goto out;
136 }
137 EXPORT_SYMBOL(atm_dev_register);
138
139 void atm_dev_deregister(struct atm_dev *dev)
140 {
141         BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags));
142         set_bit(ATM_DF_REMOVED, &dev->flags);
143
144         /*
145          * if we remove current device from atm_devs list, new device
146          * with same number can appear, such we need deregister proc,
147          * release async all vccs and remove them from vccs list too
148          */
149         mutex_lock(&atm_dev_mutex);
150         list_del(&dev->dev_list);
151         mutex_unlock(&atm_dev_mutex);
152
153         atm_dev_release_vccs(dev);
154         atm_unregister_sysfs(dev);
155         atm_proc_dev_deregister(dev);
156
157         atm_dev_put(dev);
158 }
159 EXPORT_SYMBOL(atm_dev_deregister);
160
161 static void copy_aal_stats(struct k_atm_aal_stats *from,
162     struct atm_aal_stats *to)
163 {
164 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
165         __AAL_STAT_ITEMS
166 #undef __HANDLE_ITEM
167 }
168
169 static void subtract_aal_stats(struct k_atm_aal_stats *from,
170     struct atm_aal_stats *to)
171 {
172 #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
173         __AAL_STAT_ITEMS
174 #undef __HANDLE_ITEM
175 }
176
177 static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
178                        int zero)
179 {
180         struct atm_dev_stats tmp;
181         int error = 0;
182
183         copy_aal_stats(&dev->stats.aal0, &tmp.aal0);
184         copy_aal_stats(&dev->stats.aal34, &tmp.aal34);
185         copy_aal_stats(&dev->stats.aal5, &tmp.aal5);
186         if (arg)
187                 error = copy_to_user(arg, &tmp, sizeof(tmp));
188         if (zero && !error) {
189                 subtract_aal_stats(&dev->stats.aal0, &tmp.aal0);
190                 subtract_aal_stats(&dev->stats.aal34, &tmp.aal34);
191                 subtract_aal_stats(&dev->stats.aal5, &tmp.aal5);
192         }
193         return error ? -EFAULT : 0;
194 }
195
196 int atm_getnames(void __user *buf, int __user *iobuf_len)
197 {
198         int error, len, size = 0;
199         struct atm_dev *dev;
200         struct list_head *p;
201         int *tmp_buf, *tmp_p;
202
203         if (get_user(len, iobuf_len))
204                 return -EFAULT;
205         mutex_lock(&atm_dev_mutex);
206         list_for_each(p, &atm_devs)
207                 size += sizeof(int);
208         if (size > len) {
209                 mutex_unlock(&atm_dev_mutex);
210                 return -E2BIG;
211         }
212         tmp_buf = kmalloc(size, GFP_ATOMIC);
213         if (!tmp_buf) {
214                 mutex_unlock(&atm_dev_mutex);
215                 return -ENOMEM;
216         }
217         tmp_p = tmp_buf;
218         list_for_each(p, &atm_devs) {
219                 dev = list_entry(p, struct atm_dev, dev_list);
220                 *tmp_p++ = dev->number;
221         }
222         mutex_unlock(&atm_dev_mutex);
223         error = ((copy_to_user(buf, tmp_buf, size)) ||
224                  put_user(size, iobuf_len))
225                 ? -EFAULT : 0;
226         kfree(tmp_buf);
227         return error;
228 }
229
230 int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
231                   int number, int compat)
232 {
233         int error, len, size = 0;
234         struct atm_dev *dev;
235
236         if (get_user(len, sioc_len))
237                 return -EFAULT;
238
239         dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
240                                       number);
241         if (!dev)
242                 return -ENODEV;
243
244         switch (cmd) {
245         case ATM_GETTYPE:
246                 size = strlen(dev->type) + 1;
247                 if (copy_to_user(buf, dev->type, size)) {
248                         error = -EFAULT;
249                         goto done;
250                 }
251                 break;
252         case ATM_GETESI:
253                 size = ESI_LEN;
254                 if (copy_to_user(buf, dev->esi, size)) {
255                         error = -EFAULT;
256                         goto done;
257                 }
258                 break;
259         case ATM_SETESI:
260         {
261                 int i;
262
263                 for (i = 0; i < ESI_LEN; i++)
264                         if (dev->esi[i]) {
265                                 error = -EEXIST;
266                                 goto done;
267                         }
268         }
269                 fallthrough;
270         case ATM_SETESIF:
271         {
272                 unsigned char esi[ESI_LEN];
273
274                 if (!capable(CAP_NET_ADMIN)) {
275                         error = -EPERM;
276                         goto done;
277                 }
278                 if (copy_from_user(esi, buf, ESI_LEN)) {
279                         error = -EFAULT;
280                         goto done;
281                 }
282                 memcpy(dev->esi, esi, ESI_LEN);
283                 error =  ESI_LEN;
284                 goto done;
285         }
286         case ATM_GETSTATZ:
287                 if (!capable(CAP_NET_ADMIN)) {
288                         error = -EPERM;
289                         goto done;
290                 }
291                 fallthrough;
292         case ATM_GETSTAT:
293                 size = sizeof(struct atm_dev_stats);
294                 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
295                 if (error)
296                         goto done;
297                 break;
298         case ATM_GETCIRANGE:
299                 size = sizeof(struct atm_cirange);
300                 if (copy_to_user(buf, &dev->ci_range, size)) {
301                         error = -EFAULT;
302                         goto done;
303                 }
304                 break;
305         case ATM_GETLINKRATE:
306                 size = sizeof(int);
307                 if (copy_to_user(buf, &dev->link_rate, size)) {
308                         error = -EFAULT;
309                         goto done;
310                 }
311                 break;
312         case ATM_RSTADDR:
313                 if (!capable(CAP_NET_ADMIN)) {
314                         error = -EPERM;
315                         goto done;
316                 }
317                 atm_reset_addr(dev, ATM_ADDR_LOCAL);
318                 break;
319         case ATM_ADDADDR:
320         case ATM_DELADDR:
321         case ATM_ADDLECSADDR:
322         case ATM_DELLECSADDR:
323         {
324                 struct sockaddr_atmsvc addr;
325
326                 if (!capable(CAP_NET_ADMIN)) {
327                         error = -EPERM;
328                         goto done;
329                 }
330
331                 if (copy_from_user(&addr, buf, sizeof(addr))) {
332                         error = -EFAULT;
333                         goto done;
334                 }
335                 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
336                         error = atm_add_addr(dev, &addr,
337                                              (cmd == ATM_ADDADDR ?
338                                               ATM_ADDR_LOCAL : ATM_ADDR_LECS));
339                 else
340                         error = atm_del_addr(dev, &addr,
341                                              (cmd == ATM_DELADDR ?
342                                               ATM_ADDR_LOCAL : ATM_ADDR_LECS));
343                 goto done;
344         }
345         case ATM_GETADDR:
346         case ATM_GETLECSADDR:
347                 error = atm_get_addr(dev, buf, len,
348                                      (cmd == ATM_GETADDR ?
349                                       ATM_ADDR_LOCAL : ATM_ADDR_LECS));
350                 if (error < 0)
351                         goto done;
352                 size = error;
353                 /* may return 0, but later on size == 0 means "don't
354                    write the length" */
355                 error = put_user(size, sioc_len) ? -EFAULT : 0;
356                 goto done;
357         case ATM_SETLOOP:
358                 if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
359                     __ATM_LM_XTLOC((int) (unsigned long) buf) >
360                     __ATM_LM_XTRMT((int) (unsigned long) buf)) {
361                         error = -EINVAL;
362                         goto done;
363                 }
364                 fallthrough;
365         case ATM_SETCIRANGE:
366         case SONET_GETSTATZ:
367         case SONET_SETDIAG:
368         case SONET_CLRDIAG:
369         case SONET_SETFRAMING:
370                 if (!capable(CAP_NET_ADMIN)) {
371                         error = -EPERM;
372                         goto done;
373                 }
374                 fallthrough;
375         default:
376                 if (IS_ENABLED(CONFIG_COMPAT) && compat) {
377 #ifdef CONFIG_COMPAT
378                         if (!dev->ops->compat_ioctl) {
379                                 error = -EINVAL;
380                                 goto done;
381                         }
382                         size = dev->ops->compat_ioctl(dev, cmd, buf);
383 #endif
384                 } else {
385                         if (!dev->ops->ioctl) {
386                                 error = -EINVAL;
387                                 goto done;
388                         }
389                         size = dev->ops->ioctl(dev, cmd, buf);
390                 }
391                 if (size < 0) {
392                         error = (size == -ENOIOCTLCMD ? -ENOTTY : size);
393                         goto done;
394                 }
395         }
396
397         if (size)
398                 error = put_user(size, sioc_len) ? -EFAULT : 0;
399         else
400                 error = 0;
401 done:
402         atm_dev_put(dev);
403         return error;
404 }
405
406 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
407 {
408         mutex_lock(&atm_dev_mutex);
409         return seq_list_start_head(&atm_devs, *pos);
410 }
411
412 void atm_dev_seq_stop(struct seq_file *seq, void *v)
413 {
414         mutex_unlock(&atm_dev_mutex);
415 }
416
417 void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
418 {
419         return seq_list_next(v, &atm_devs, pos);
420 }