aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/atm/common.c338
1 files changed, 173 insertions, 165 deletions
diff --git a/net/atm/common.c b/net/atm/common.c
index 17f7e5f2131b..74d095a081e3 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -19,11 +19,10 @@
19#include <linux/bitops.h> 19#include <linux/bitops.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <net/sock.h> /* struct sock */ 21#include <net/sock.h> /* struct sock */
22#include <linux/uaccess.h>
23#include <linux/poll.h>
22 24
23#include <asm/uaccess.h>
24#include <asm/atomic.h> 25#include <asm/atomic.h>
25#include <asm/poll.h>
26
27 26
28#include "resources.h" /* atm_find_dev */ 27#include "resources.h" /* atm_find_dev */
29#include "common.h" /* prototypes */ 28#include "common.h" /* prototypes */
@@ -32,13 +31,15 @@
32#include "signaling.h" /* for WAITING and sigd_attach */ 31#include "signaling.h" /* for WAITING and sigd_attach */
33 32
34struct hlist_head vcc_hash[VCC_HTABLE_SIZE]; 33struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
34EXPORT_SYMBOL(vcc_hash);
35
35DEFINE_RWLOCK(vcc_sklist_lock); 36DEFINE_RWLOCK(vcc_sklist_lock);
37EXPORT_SYMBOL(vcc_sklist_lock);
36 38
37static void __vcc_insert_socket(struct sock *sk) 39static void __vcc_insert_socket(struct sock *sk)
38{ 40{
39 struct atm_vcc *vcc = atm_sk(sk); 41 struct atm_vcc *vcc = atm_sk(sk);
40 struct hlist_head *head = &vcc_hash[vcc->vci & 42 struct hlist_head *head = &vcc_hash[vcc->vci & (VCC_HTABLE_SIZE - 1)];
41 (VCC_HTABLE_SIZE - 1)];
42 sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); 43 sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1);
43 sk_add_node(sk, head); 44 sk_add_node(sk, head);
44} 45}
@@ -49,6 +50,7 @@ void vcc_insert_socket(struct sock *sk)
49 __vcc_insert_socket(sk); 50 __vcc_insert_socket(sk);
50 write_unlock_irq(&vcc_sklist_lock); 51 write_unlock_irq(&vcc_sklist_lock);
51} 52}
53EXPORT_SYMBOL(vcc_insert_socket);
52 54
53static void vcc_remove_socket(struct sock *sk) 55static void vcc_remove_socket(struct sock *sk)
54{ 56{
@@ -57,8 +59,7 @@ static void vcc_remove_socket(struct sock *sk)
57 write_unlock_irq(&vcc_sklist_lock); 59 write_unlock_irq(&vcc_sklist_lock);
58} 60}
59 61
60 62static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
61static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
62{ 63{
63 struct sk_buff *skb; 64 struct sk_buff *skb;
64 struct sock *sk = sk_atm(vcc); 65 struct sock *sk = sk_atm(vcc);
@@ -70,23 +71,20 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
70 } 71 }
71 while (!(skb = alloc_skb(size, GFP_KERNEL))) 72 while (!(skb = alloc_skb(size, GFP_KERNEL)))
72 schedule(); 73 schedule();
73 pr_debug("AlTx %d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); 74 pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
74 atomic_add(skb->truesize, &sk->sk_wmem_alloc); 75 atomic_add(skb->truesize, &sk->sk_wmem_alloc);
75 return skb; 76 return skb;
76} 77}
77 78
78
79EXPORT_SYMBOL(vcc_hash);
80EXPORT_SYMBOL(vcc_sklist_lock);
81EXPORT_SYMBOL(vcc_insert_socket);
82
83static void vcc_sock_destruct(struct sock *sk) 79static void vcc_sock_destruct(struct sock *sk)
84{ 80{
85 if (atomic_read(&sk->sk_rmem_alloc)) 81 if (atomic_read(&sk->sk_rmem_alloc))
86 printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_rmem_alloc)); 82 printk(KERN_DEBUG "%s: rmem leakage (%d bytes) detected.\n",
83 __func__, atomic_read(&sk->sk_rmem_alloc));
87 84
88 if (atomic_read(&sk->sk_wmem_alloc)) 85 if (atomic_read(&sk->sk_wmem_alloc))
89 printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_wmem_alloc)); 86 printk(KERN_DEBUG "%s: wmem leakage (%d bytes) detected.\n",
87 __func__, atomic_read(&sk->sk_wmem_alloc));
90} 88}
91 89
92static void vcc_def_wakeup(struct sock *sk) 90static void vcc_def_wakeup(struct sock *sk)
@@ -142,8 +140,8 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
142 140
143 vcc = atm_sk(sk); 141 vcc = atm_sk(sk);
144 vcc->dev = NULL; 142 vcc->dev = NULL;
145 memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); 143 memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc));
146 memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); 144 memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc));
147 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ 145 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
148 atomic_set(&sk->sk_wmem_alloc, 1); 146 atomic_set(&sk->sk_wmem_alloc, 1);
149 atomic_set(&sk->sk_rmem_alloc, 0); 147 atomic_set(&sk->sk_rmem_alloc, 0);
@@ -156,7 +154,6 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
156 return 0; 154 return 0;
157} 155}
158 156
159
160static void vcc_destroy_socket(struct sock *sk) 157static void vcc_destroy_socket(struct sock *sk)
161{ 158{
162 struct atm_vcc *vcc = atm_sk(sk); 159 struct atm_vcc *vcc = atm_sk(sk);
@@ -171,7 +168,7 @@ static void vcc_destroy_socket(struct sock *sk)
171 vcc->push(vcc, NULL); /* atmarpd has no push */ 168 vcc->push(vcc, NULL); /* atmarpd has no push */
172 169
173 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 170 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
174 atm_return(vcc,skb->truesize); 171 atm_return(vcc, skb->truesize);
175 kfree_skb(skb); 172 kfree_skb(skb);
176 } 173 }
177 174
@@ -182,7 +179,6 @@ static void vcc_destroy_socket(struct sock *sk)
182 vcc_remove_socket(sk); 179 vcc_remove_socket(sk);
183} 180}
184 181
185
186int vcc_release(struct socket *sock) 182int vcc_release(struct socket *sock)
187{ 183{
188 struct sock *sk = sock->sk; 184 struct sock *sk = sock->sk;
@@ -197,7 +193,6 @@ int vcc_release(struct socket *sock)
197 return 0; 193 return 0;
198} 194}
199 195
200
201void vcc_release_async(struct atm_vcc *vcc, int reply) 196void vcc_release_async(struct atm_vcc *vcc, int reply)
202{ 197{
203 struct sock *sk = sk_atm(vcc); 198 struct sock *sk = sk_atm(vcc);
@@ -208,8 +203,6 @@ void vcc_release_async(struct atm_vcc *vcc, int reply)
208 clear_bit(ATM_VF_WAITING, &vcc->flags); 203 clear_bit(ATM_VF_WAITING, &vcc->flags);
209 sk->sk_state_change(sk); 204 sk->sk_state_change(sk);
210} 205}
211
212
213EXPORT_SYMBOL(vcc_release_async); 206EXPORT_SYMBOL(vcc_release_async);
214 207
215 208
@@ -235,36 +228,37 @@ void atm_dev_release_vccs(struct atm_dev *dev)
235 write_unlock_irq(&vcc_sklist_lock); 228 write_unlock_irq(&vcc_sklist_lock);
236} 229}
237 230
238 231static int adjust_tp(struct atm_trafprm *tp, unsigned char aal)
239static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
240{ 232{
241 int max_sdu; 233 int max_sdu;
242 234
243 if (!tp->traffic_class) return 0; 235 if (!tp->traffic_class)
236 return 0;
244 switch (aal) { 237 switch (aal) {
245 case ATM_AAL0: 238 case ATM_AAL0:
246 max_sdu = ATM_CELL_SIZE-1; 239 max_sdu = ATM_CELL_SIZE-1;
247 break; 240 break;
248 case ATM_AAL34: 241 case ATM_AAL34:
249 max_sdu = ATM_MAX_AAL34_PDU; 242 max_sdu = ATM_MAX_AAL34_PDU;
250 break; 243 break;
251 default: 244 default:
252 pr_warning("AAL problems ... (%d)\n", aal); 245 pr_warning("AAL problems ... (%d)\n", aal);
253 /* fall through */ 246 /* fall through */
254 case ATM_AAL5: 247 case ATM_AAL5:
255 max_sdu = ATM_MAX_AAL5_PDU; 248 max_sdu = ATM_MAX_AAL5_PDU;
256 } 249 }
257 if (!tp->max_sdu) tp->max_sdu = max_sdu; 250 if (!tp->max_sdu)
258 else if (tp->max_sdu > max_sdu) return -EINVAL; 251 tp->max_sdu = max_sdu;
259 if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV; 252 else if (tp->max_sdu > max_sdu)
253 return -EINVAL;
254 if (!tp->max_cdv)
255 tp->max_cdv = ATM_MAX_CDV;
260 return 0; 256 return 0;
261} 257}
262 258
263
264static int check_ci(const struct atm_vcc *vcc, short vpi, int vci) 259static int check_ci(const struct atm_vcc *vcc, short vpi, int vci)
265{ 260{
266 struct hlist_head *head = &vcc_hash[vci & 261 struct hlist_head *head = &vcc_hash[vci & (VCC_HTABLE_SIZE - 1)];
267 (VCC_HTABLE_SIZE - 1)];
268 struct hlist_node *node; 262 struct hlist_node *node;
269 struct sock *s; 263 struct sock *s;
270 struct atm_vcc *walk; 264 struct atm_vcc *walk;
@@ -288,7 +282,6 @@ static int check_ci(const struct atm_vcc *vcc, short vpi, int vci)
288 return 0; 282 return 0;
289} 283}
290 284
291
292static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci) 285static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci)
293{ 286{
294 static short p; /* poor man's per-device cache */ 287 static short p; /* poor man's per-device cache */
@@ -326,14 +319,13 @@ static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci)
326 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) && 319 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
327 *vpi == ATM_VPI_ANY) { 320 *vpi == ATM_VPI_ANY) {
328 p++; 321 p++;
329 if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0; 322 if (p >= 1 << vcc->dev->ci_range.vpi_bits)
323 p = 0;
330 } 324 }
331 } 325 } while (old_p != p || old_c != c);
332 while (old_p != p || old_c != c);
333 return -EADDRINUSE; 326 return -EADDRINUSE;
334} 327}
335 328
336
337static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, 329static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
338 int vci) 330 int vci)
339{ 331{
@@ -361,27 +353,29 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
361 __vcc_insert_socket(sk); 353 __vcc_insert_socket(sk);
362 write_unlock_irq(&vcc_sklist_lock); 354 write_unlock_irq(&vcc_sklist_lock);
363 switch (vcc->qos.aal) { 355 switch (vcc->qos.aal) {
364 case ATM_AAL0: 356 case ATM_AAL0:
365 error = atm_init_aal0(vcc); 357 error = atm_init_aal0(vcc);
366 vcc->stats = &dev->stats.aal0; 358 vcc->stats = &dev->stats.aal0;
367 break; 359 break;
368 case ATM_AAL34: 360 case ATM_AAL34:
369 error = atm_init_aal34(vcc); 361 error = atm_init_aal34(vcc);
370 vcc->stats = &dev->stats.aal34; 362 vcc->stats = &dev->stats.aal34;
371 break; 363 break;
372 case ATM_NO_AAL: 364 case ATM_NO_AAL:
373 /* ATM_AAL5 is also used in the "0 for default" case */ 365 /* ATM_AAL5 is also used in the "0 for default" case */
374 vcc->qos.aal = ATM_AAL5; 366 vcc->qos.aal = ATM_AAL5;
375 /* fall through */ 367 /* fall through */
376 case ATM_AAL5: 368 case ATM_AAL5:
377 error = atm_init_aal5(vcc); 369 error = atm_init_aal5(vcc);
378 vcc->stats = &dev->stats.aal5; 370 vcc->stats = &dev->stats.aal5;
379 break; 371 break;
380 default: 372 default:
381 error = -EPROTOTYPE; 373 error = -EPROTOTYPE;
382 } 374 }
383 if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); 375 if (!error)
384 if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); 376 error = adjust_tp(&vcc->qos.txtp, vcc->qos.aal);
377 if (!error)
378 error = adjust_tp(&vcc->qos.rxtp, vcc->qos.aal);
385 if (error) 379 if (error)
386 goto fail; 380 goto fail;
387 pr_debug("VCC %d.%d, AAL %d\n", vpi, vci, vcc->qos.aal); 381 pr_debug("VCC %d.%d, AAL %d\n", vpi, vci, vcc->qos.aal);
@@ -397,7 +391,8 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
397 vcc->qos.rxtp.max_sdu); 391 vcc->qos.rxtp.max_sdu);
398 392
399 if (dev->ops->open) { 393 if (dev->ops->open) {
400 if ((error = dev->ops->open(vcc))) 394 error = dev->ops->open(vcc);
395 if (error)
401 goto fail; 396 goto fail;
402 } 397 }
403 return 0; 398 return 0;
@@ -411,7 +406,6 @@ fail_module_put:
411 return error; 406 return error;
412} 407}
413 408
414
415int vcc_connect(struct socket *sock, int itf, short vpi, int vci) 409int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
416{ 410{
417 struct atm_dev *dev; 411 struct atm_dev *dev;
@@ -427,16 +421,16 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
427 return -EINVAL; 421 return -EINVAL;
428 422
429 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) 423 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
430 clear_bit(ATM_VF_PARTIAL,&vcc->flags); 424 clear_bit(ATM_VF_PARTIAL, &vcc->flags);
431 else 425 else
432 if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) 426 if (test_bit(ATM_VF_PARTIAL, &vcc->flags))
433 return -EINVAL; 427 return -EINVAL;
434 pr_debug("(TX: cl %d,bw %d-%d,sdu %d; " 428 pr_debug("(TX: cl %d,bw %d-%d,sdu %d; "
435 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", 429 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
436 vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr, 430 vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,
437 vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu, 431 vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu,
438 vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr, 432 vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr,
439 vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, 433 vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_sdu,
440 vcc->qos.aal == ATM_AAL5 ? "" : 434 vcc->qos.aal == ATM_AAL5 ? "" :
441 vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ", 435 vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ",
442 vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); 436 vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
@@ -446,12 +440,14 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
446 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) 440 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
447 return -EINVAL; 441 return -EINVAL;
448 if (likely(itf != ATM_ITF_ANY)) { 442 if (likely(itf != ATM_ITF_ANY)) {
449 dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); 443 dev = try_then_request_module(atm_dev_lookup(itf),
444 "atm-device-%d", itf);
450 } else { 445 } else {
451 dev = NULL; 446 dev = NULL;
452 mutex_lock(&atm_dev_mutex); 447 mutex_lock(&atm_dev_mutex);
453 if (!list_empty(&atm_devs)) { 448 if (!list_empty(&atm_devs)) {
454 dev = list_entry(atm_devs.next, struct atm_dev, dev_list); 449 dev = list_entry(atm_devs.next,
450 struct atm_dev, dev_list);
455 atm_dev_hold(dev); 451 atm_dev_hold(dev);
456 } 452 }
457 mutex_unlock(&atm_dev_mutex); 453 mutex_unlock(&atm_dev_mutex);
@@ -464,13 +460,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
464 return error; 460 return error;
465 } 461 }
466 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) 462 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
467 set_bit(ATM_VF_PARTIAL,&vcc->flags); 463 set_bit(ATM_VF_PARTIAL, &vcc->flags);
468 if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags)) 464 if (test_bit(ATM_VF_READY, &ATM_SD(sock)->flags))
469 sock->state = SS_CONNECTED; 465 sock->state = SS_CONNECTED;
470 return 0; 466 return 0;
471} 467}
472 468
473
474int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, 469int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
475 size_t size, int flags) 470 size_t size, int flags)
476{ 471{
@@ -484,8 +479,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
484 if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */ 479 if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */
485 return -EOPNOTSUPP; 480 return -EOPNOTSUPP;
486 vcc = ATM_SD(sock); 481 vcc = ATM_SD(sock);
487 if (test_bit(ATM_VF_RELEASED,&vcc->flags) || 482 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
488 test_bit(ATM_VF_CLOSE,&vcc->flags) || 483 test_bit(ATM_VF_CLOSE, &vcc->flags) ||
489 !test_bit(ATM_VF_READY, &vcc->flags)) 484 !test_bit(ATM_VF_READY, &vcc->flags))
490 return 0; 485 return 0;
491 486
@@ -509,7 +504,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
509 return copied; 504 return copied;
510} 505}
511 506
512
513int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, 507int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
514 size_t total_len) 508 size_t total_len)
515{ 509{
@@ -517,7 +511,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
517 DEFINE_WAIT(wait); 511 DEFINE_WAIT(wait);
518 struct atm_vcc *vcc; 512 struct atm_vcc *vcc;
519 struct sk_buff *skb; 513 struct sk_buff *skb;
520 int eff,error; 514 int eff, error;
521 const void __user *buff; 515 const void __user *buff;
522 int size; 516 int size;
523 517
@@ -556,7 +550,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
556 eff = (size+3) & ~3; /* align to word boundary */ 550 eff = (size+3) & ~3; /* align to word boundary */
557 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); 551 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
558 error = 0; 552 error = 0;
559 while (!(skb = alloc_tx(vcc,eff))) { 553 while (!(skb = alloc_tx(vcc, eff))) {
560 if (m->msg_flags & MSG_DONTWAIT) { 554 if (m->msg_flags & MSG_DONTWAIT) {
561 error = -EAGAIN; 555 error = -EAGAIN;
562 break; 556 break;
@@ -566,9 +560,9 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
566 error = -ERESTARTSYS; 560 error = -ERESTARTSYS;
567 break; 561 break;
568 } 562 }
569 if (test_bit(ATM_VF_RELEASED,&vcc->flags) || 563 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
570 test_bit(ATM_VF_CLOSE,&vcc->flags) || 564 test_bit(ATM_VF_CLOSE, &vcc->flags) ||
571 !test_bit(ATM_VF_READY,&vcc->flags)) { 565 !test_bit(ATM_VF_READY, &vcc->flags)) {
572 error = -EPIPE; 566 error = -EPIPE;
573 send_sig(SIGPIPE, current, 0); 567 send_sig(SIGPIPE, current, 0);
574 break; 568 break;
@@ -580,20 +574,20 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
580 goto out; 574 goto out;
581 skb->dev = NULL; /* for paths shared with net_device interfaces */ 575 skb->dev = NULL; /* for paths shared with net_device interfaces */
582 ATM_SKB(skb)->atm_options = vcc->atm_options; 576 ATM_SKB(skb)->atm_options = vcc->atm_options;
583 if (copy_from_user(skb_put(skb,size),buff,size)) { 577 if (copy_from_user(skb_put(skb, size), buff, size)) {
584 kfree_skb(skb); 578 kfree_skb(skb);
585 error = -EFAULT; 579 error = -EFAULT;
586 goto out; 580 goto out;
587 } 581 }
588 if (eff != size) memset(skb->data+size,0,eff-size); 582 if (eff != size)
589 error = vcc->dev->ops->send(vcc,skb); 583 memset(skb->data + size, 0, eff-size);
584 error = vcc->dev->ops->send(vcc, skb);
590 error = error ? error : size; 585 error = error ? error : size;
591out: 586out:
592 release_sock(sk); 587 release_sock(sk);
593 return error; 588 return error;
594} 589}
595 590
596
597unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) 591unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
598{ 592{
599 struct sock *sk = sock->sk; 593 struct sock *sk = sock->sk;
@@ -629,8 +623,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
629 return mask; 623 return mask;
630} 624}
631 625
632 626static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
633static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
634{ 627{
635 int error; 628 int error;
636 629
@@ -642,25 +635,31 @@ static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
642 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || 635 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
643 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) 636 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
644 return -EINVAL; 637 return -EINVAL;
645 error = adjust_tp(&qos->txtp,qos->aal); 638 error = adjust_tp(&qos->txtp, qos->aal);
646 if (!error) error = adjust_tp(&qos->rxtp,qos->aal); 639 if (!error)
647 if (error) return error; 640 error = adjust_tp(&qos->rxtp, qos->aal);
648 if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; 641 if (error)
642 return error;
643 if (!vcc->dev->ops->change_qos)
644 return -EOPNOTSUPP;
649 if (sk_atm(vcc)->sk_family == AF_ATMPVC) 645 if (sk_atm(vcc)->sk_family == AF_ATMPVC)
650 return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); 646 return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
651 return svc_change_qos(vcc,qos); 647 return svc_change_qos(vcc, qos);
652} 648}
653 649
654
655static int check_tp(const struct atm_trafprm *tp) 650static int check_tp(const struct atm_trafprm *tp)
656{ 651{
657 /* @@@ Should be merged with adjust_tp */ 652 /* @@@ Should be merged with adjust_tp */
658 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0; 653 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS)
654 return 0;
659 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr && 655 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
660 !tp->max_pcr) return -EINVAL; 656 !tp->max_pcr)
661 if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL; 657 return -EINVAL;
658 if (tp->min_pcr == ATM_MAX_PCR)
659 return -EINVAL;
662 if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR && 660 if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR &&
663 tp->min_pcr > tp->max_pcr) return -EINVAL; 661 tp->min_pcr > tp->max_pcr)
662 return -EINVAL;
664 /* 663 /*
665 * We allow pcr to be outside [min_pcr,max_pcr], because later 664 * We allow pcr to be outside [min_pcr,max_pcr], because later
666 * adjustment may still push it in the valid range. 665 * adjustment may still push it in the valid range.
@@ -668,7 +667,6 @@ static int check_tp(const struct atm_trafprm *tp)
668 return 0; 667 return 0;
669} 668}
670 669
671
672static int check_qos(const struct atm_qos *qos) 670static int check_qos(const struct atm_qos *qos)
673{ 671{
674 int error; 672 int error;
@@ -678,9 +676,11 @@ static int check_qos(const struct atm_qos *qos)
678 if (qos->txtp.traffic_class != qos->rxtp.traffic_class && 676 if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
679 qos->txtp.traffic_class && qos->rxtp.traffic_class && 677 qos->txtp.traffic_class && qos->rxtp.traffic_class &&
680 qos->txtp.traffic_class != ATM_ANYCLASS && 678 qos->txtp.traffic_class != ATM_ANYCLASS &&
681 qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL; 679 qos->rxtp.traffic_class != ATM_ANYCLASS)
680 return -EINVAL;
682 error = check_tp(&qos->txtp); 681 error = check_tp(&qos->txtp);
683 if (error) return error; 682 if (error)
683 return error;
684 return check_tp(&qos->rxtp); 684 return check_tp(&qos->rxtp);
685} 685}
686 686
@@ -696,37 +696,41 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
696 696
697 vcc = ATM_SD(sock); 697 vcc = ATM_SD(sock);
698 switch (optname) { 698 switch (optname) {
699 case SO_ATMQOS: 699 case SO_ATMQOS:
700 { 700 {
701 struct atm_qos qos; 701 struct atm_qos qos;
702 702
703 if (copy_from_user(&qos,optval,sizeof(qos))) 703 if (copy_from_user(&qos, optval, sizeof(qos)))
704 return -EFAULT; 704 return -EFAULT;
705 error = check_qos(&qos); 705 error = check_qos(&qos);
706 if (error) return error; 706 if (error)
707 if (sock->state == SS_CONNECTED) 707 return error;
708 return atm_change_qos(vcc,&qos); 708 if (sock->state == SS_CONNECTED)
709 if (sock->state != SS_UNCONNECTED) 709 return atm_change_qos(vcc, &qos);
710 return -EBADFD; 710 if (sock->state != SS_UNCONNECTED)
711 vcc->qos = qos; 711 return -EBADFD;
712 set_bit(ATM_VF_HASQOS,&vcc->flags); 712 vcc->qos = qos;
713 return 0; 713 set_bit(ATM_VF_HASQOS, &vcc->flags);
714 } 714 return 0;
715 case SO_SETCLP:
716 if (get_user(value,(unsigned long __user *)optval))
717 return -EFAULT;
718 if (value) vcc->atm_options |= ATM_ATMOPT_CLP;
719 else vcc->atm_options &= ~ATM_ATMOPT_CLP;
720 return 0;
721 default:
722 if (level == SOL_SOCKET) return -EINVAL;
723 break;
724 } 715 }
725 if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL; 716 case SO_SETCLP:
726 return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen); 717 if (get_user(value, (unsigned long __user *)optval))
718 return -EFAULT;
719 if (value)
720 vcc->atm_options |= ATM_ATMOPT_CLP;
721 else
722 vcc->atm_options &= ~ATM_ATMOPT_CLP;
723 return 0;
724 default:
725 if (level == SOL_SOCKET)
726 return -EINVAL;
727 break;
728 }
729 if (!vcc->dev || !vcc->dev->ops->setsockopt)
730 return -EINVAL;
731 return vcc->dev->ops->setsockopt(vcc, level, optname, optval, optlen);
727} 732}
728 733
729
730int vcc_getsockopt(struct socket *sock, int level, int optname, 734int vcc_getsockopt(struct socket *sock, int level, int optname,
731 char __user *optval, int __user *optlen) 735 char __user *optval, int __user *optlen)
732{ 736{
@@ -740,33 +744,33 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,
740 744
741 vcc = ATM_SD(sock); 745 vcc = ATM_SD(sock);
742 switch (optname) { 746 switch (optname) {
743 case SO_ATMQOS: 747 case SO_ATMQOS:
744 if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) 748 if (!test_bit(ATM_VF_HASQOS, &vcc->flags))
745 return -EINVAL; 749 return -EINVAL;
746 return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ? 750 return copy_to_user(optval, &vcc->qos, sizeof(vcc->qos))
747 -EFAULT : 0; 751 ? -EFAULT : 0;
748 case SO_SETCLP: 752 case SO_SETCLP:
749 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 753 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0,
750 0,(unsigned long __user *)optval) ? -EFAULT : 0; 754 (unsigned long __user *)optval) ? -EFAULT : 0;
751 case SO_ATMPVC: 755 case SO_ATMPVC:
752 { 756 {
753 struct sockaddr_atmpvc pvc; 757 struct sockaddr_atmpvc pvc;
754 758
755 if (!vcc->dev || 759 if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))
756 !test_bit(ATM_VF_ADDR,&vcc->flags)) 760 return -ENOTCONN;
757 return -ENOTCONN; 761 pvc.sap_family = AF_ATMPVC;
758 pvc.sap_family = AF_ATMPVC; 762 pvc.sap_addr.itf = vcc->dev->number;
759 pvc.sap_addr.itf = vcc->dev->number; 763 pvc.sap_addr.vpi = vcc->vpi;
760 pvc.sap_addr.vpi = vcc->vpi; 764 pvc.sap_addr.vci = vcc->vci;
761 pvc.sap_addr.vci = vcc->vci; 765 return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0;
762 return copy_to_user(optval,&pvc,sizeof(pvc)) ? 766 }
763 -EFAULT : 0; 767 default:
764 } 768 if (level == SOL_SOCKET)
765 default: 769 return -EINVAL;
766 if (level == SOL_SOCKET) return -EINVAL;
767 break; 770 break;
768 } 771 }
769 if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; 772 if (!vcc->dev || !vcc->dev->ops->getsockopt)
773 return -EINVAL;
770 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); 774 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
771} 775}
772 776
@@ -774,22 +778,26 @@ static int __init atm_init(void)
774{ 778{
775 int error; 779 int error;
776 780
777 if ((error = proto_register(&vcc_proto, 0)) < 0) 781 error = proto_register(&vcc_proto, 0);
782 if (error < 0)
778 goto out; 783 goto out;
779 784 error = atmpvc_init();
780 if ((error = atmpvc_init()) < 0) { 785 if (error < 0) {
781 pr_err("atmpvc_init() failed with %d\n", error); 786 pr_err("atmpvc_init() failed with %d\n", error);
782 goto out_unregister_vcc_proto; 787 goto out_unregister_vcc_proto;
783 } 788 }
784 if ((error = atmsvc_init()) < 0) { 789 error = atmsvc_init();
790 if (error < 0) {
785 pr_err("atmsvc_init() failed with %d\n", error); 791 pr_err("atmsvc_init() failed with %d\n", error);
786 goto out_atmpvc_exit; 792 goto out_atmpvc_exit;
787 } 793 }
788 if ((error = atm_proc_init()) < 0) { 794 error = atm_proc_init();
795 if (error < 0) {
789 pr_err("atm_proc_init() failed with %d\n", error); 796 pr_err("atm_proc_init() failed with %d\n", error);
790 goto out_atmsvc_exit; 797 goto out_atmsvc_exit;
791 } 798 }
792 if ((error = atm_sysfs_init()) < 0) { 799 error = atm_sysfs_init();
800 if (error < 0) {
793 pr_err("atm_sysfs_init() failed with %d\n", error); 801 pr_err("atm_sysfs_init() failed with %d\n", error);
794 goto out_atmproc_exit; 802 goto out_atmproc_exit;
795 } 803 }