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