aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/atm/common.c')
-rw-r--r--net/atm/common.c386
1 files changed, 200 insertions, 186 deletions
diff --git a/net/atm/common.c b/net/atm/common.c
index d61e051e0a3f..74d095a081e3 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -2,6 +2,7 @@
2 2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4 4
5#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
5 6
6#include <linux/module.h> 7#include <linux/module.h>
7#include <linux/kmod.h> 8#include <linux/kmod.h>
@@ -18,11 +19,10 @@
18#include <linux/bitops.h> 19#include <linux/bitops.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <net/sock.h> /* struct sock */ 21#include <net/sock.h> /* struct sock */
22#include <linux/uaccess.h>
23#include <linux/poll.h>
21 24
22#include <asm/uaccess.h>
23#include <asm/atomic.h> 25#include <asm/atomic.h>
24#include <asm/poll.h>
25
26 26
27#include "resources.h" /* atm_find_dev */ 27#include "resources.h" /* atm_find_dev */
28#include "common.h" /* prototypes */ 28#include "common.h" /* prototypes */
@@ -31,13 +31,15 @@
31#include "signaling.h" /* for WAITING and sigd_attach */ 31#include "signaling.h" /* for WAITING and sigd_attach */
32 32
33struct hlist_head vcc_hash[VCC_HTABLE_SIZE]; 33struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
34EXPORT_SYMBOL(vcc_hash);
35
34DEFINE_RWLOCK(vcc_sklist_lock); 36DEFINE_RWLOCK(vcc_sklist_lock);
37EXPORT_SYMBOL(vcc_sklist_lock);
35 38
36static void __vcc_insert_socket(struct sock *sk) 39static void __vcc_insert_socket(struct sock *sk)
37{ 40{
38 struct atm_vcc *vcc = atm_sk(sk); 41 struct atm_vcc *vcc = atm_sk(sk);
39 struct hlist_head *head = &vcc_hash[vcc->vci & 42 struct hlist_head *head = &vcc_hash[vcc->vci & (VCC_HTABLE_SIZE - 1)];
40 (VCC_HTABLE_SIZE - 1)];
41 sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); 43 sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1);
42 sk_add_node(sk, head); 44 sk_add_node(sk, head);
43} 45}
@@ -48,6 +50,7 @@ void vcc_insert_socket(struct sock *sk)
48 __vcc_insert_socket(sk); 50 __vcc_insert_socket(sk);
49 write_unlock_irq(&vcc_sklist_lock); 51 write_unlock_irq(&vcc_sklist_lock);
50} 52}
53EXPORT_SYMBOL(vcc_insert_socket);
51 54
52static void vcc_remove_socket(struct sock *sk) 55static void vcc_remove_socket(struct sock *sk)
53{ 56{
@@ -56,37 +59,32 @@ static void vcc_remove_socket(struct sock *sk)
56 write_unlock_irq(&vcc_sklist_lock); 59 write_unlock_irq(&vcc_sklist_lock);
57} 60}
58 61
59 62static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
60static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
61{ 63{
62 struct sk_buff *skb; 64 struct sk_buff *skb;
63 struct sock *sk = sk_atm(vcc); 65 struct sock *sk = sk_atm(vcc);
64 66
65 if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { 67 if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
66 pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", 68 pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
67 sk_wmem_alloc_get(sk), size, 69 sk_wmem_alloc_get(sk), size, sk->sk_sndbuf);
68 sk->sk_sndbuf);
69 return NULL; 70 return NULL;
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,37 +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 printk(KERN_WARNING "ATM: AAL problems ... " 245 pr_warning("AAL problems ... (%d)\n", aal);
253 "(%d)\n",aal); 246 /* fall through */
254 /* fall through */ 247 case ATM_AAL5:
255 case ATM_AAL5: 248 max_sdu = ATM_MAX_AAL5_PDU;
256 max_sdu = ATM_MAX_AAL5_PDU;
257 } 249 }
258 if (!tp->max_sdu) tp->max_sdu = max_sdu; 250 if (!tp->max_sdu)
259 else if (tp->max_sdu > max_sdu) return -EINVAL; 251 tp->max_sdu = max_sdu;
260 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;
261 return 0; 256 return 0;
262} 257}
263 258
264
265static 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)
266{ 260{
267 struct hlist_head *head = &vcc_hash[vci & 261 struct hlist_head *head = &vcc_hash[vci & (VCC_HTABLE_SIZE - 1)];
268 (VCC_HTABLE_SIZE - 1)];
269 struct hlist_node *node; 262 struct hlist_node *node;
270 struct sock *s; 263 struct sock *s;
271 struct atm_vcc *walk; 264 struct atm_vcc *walk;
@@ -289,7 +282,6 @@ static int check_ci(const struct atm_vcc *vcc, short vpi, int vci)
289 return 0; 282 return 0;
290} 283}
291 284
292
293static 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)
294{ 286{
295 static short p; /* poor man's per-device cache */ 287 static short p; /* poor man's per-device cache */
@@ -327,14 +319,13 @@ static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci)
327 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) && 319 if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) &&
328 *vpi == ATM_VPI_ANY) { 320 *vpi == ATM_VPI_ANY) {
329 p++; 321 p++;
330 if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0; 322 if (p >= 1 << vcc->dev->ci_range.vpi_bits)
323 p = 0;
331 } 324 }
332 } 325 } while (old_p != p || old_c != c);
333 while (old_p != p || old_c != c);
334 return -EADDRINUSE; 326 return -EADDRINUSE;
335} 327}
336 328
337
338static 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,
339 int vci) 330 int vci)
340{ 331{
@@ -362,37 +353,46 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
362 __vcc_insert_socket(sk); 353 __vcc_insert_socket(sk);
363 write_unlock_irq(&vcc_sklist_lock); 354 write_unlock_irq(&vcc_sklist_lock);
364 switch (vcc->qos.aal) { 355 switch (vcc->qos.aal) {
365 case ATM_AAL0: 356 case ATM_AAL0:
366 error = atm_init_aal0(vcc); 357 error = atm_init_aal0(vcc);
367 vcc->stats = &dev->stats.aal0; 358 vcc->stats = &dev->stats.aal0;
368 break; 359 break;
369 case ATM_AAL34: 360 case ATM_AAL34:
370 error = atm_init_aal34(vcc); 361 error = atm_init_aal34(vcc);
371 vcc->stats = &dev->stats.aal34; 362 vcc->stats = &dev->stats.aal34;
372 break; 363 break;
373 case ATM_NO_AAL: 364 case ATM_NO_AAL:
374 /* ATM_AAL5 is also used in the "0 for default" case */ 365 /* ATM_AAL5 is also used in the "0 for default" case */
375 vcc->qos.aal = ATM_AAL5; 366 vcc->qos.aal = ATM_AAL5;
376 /* fall through */ 367 /* fall through */
377 case ATM_AAL5: 368 case ATM_AAL5:
378 error = atm_init_aal5(vcc); 369 error = atm_init_aal5(vcc);
379 vcc->stats = &dev->stats.aal5; 370 vcc->stats = &dev->stats.aal5;
380 break; 371 break;
381 default: 372 default:
382 error = -EPROTOTYPE; 373 error = -EPROTOTYPE;
383 } 374 }
384 if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); 375 if (!error)
385 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);
386 if (error) 379 if (error)
387 goto fail; 380 goto fail;
388 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);
389 pr_debug(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, 382 pr_debug(" TX: %d, PCR %d..%d, SDU %d\n",
390 vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); 383 vcc->qos.txtp.traffic_class,
391 pr_debug(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class, 384 vcc->qos.txtp.min_pcr,
392 vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); 385 vcc->qos.txtp.max_pcr,
386 vcc->qos.txtp.max_sdu);
387 pr_debug(" RX: %d, PCR %d..%d, SDU %d\n",
388 vcc->qos.rxtp.traffic_class,
389 vcc->qos.rxtp.min_pcr,
390 vcc->qos.rxtp.max_pcr,
391 vcc->qos.rxtp.max_sdu);
393 392
394 if (dev->ops->open) { 393 if (dev->ops->open) {
395 if ((error = dev->ops->open(vcc))) 394 error = dev->ops->open(vcc);
395 if (error)
396 goto fail; 396 goto fail;
397 } 397 }
398 return 0; 398 return 0;
@@ -406,14 +406,13 @@ fail_module_put:
406 return error; 406 return error;
407} 407}
408 408
409
410int vcc_connect(struct socket *sock, int itf, short vpi, int vci) 409int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
411{ 410{
412 struct atm_dev *dev; 411 struct atm_dev *dev;
413 struct atm_vcc *vcc = ATM_SD(sock); 412 struct atm_vcc *vcc = ATM_SD(sock);
414 int error; 413 int error;
415 414
416 pr_debug("vcc_connect (vpi %d, vci %d)\n",vpi,vci); 415 pr_debug("(vpi %d, vci %d)\n", vpi, vci);
417 if (sock->state == SS_CONNECTED) 416 if (sock->state == SS_CONNECTED)
418 return -EISCONN; 417 return -EISCONN;
419 if (sock->state != SS_UNCONNECTED) 418 if (sock->state != SS_UNCONNECTED)
@@ -422,30 +421,33 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
422 return -EINVAL; 421 return -EINVAL;
423 422
424 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) 423 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
425 clear_bit(ATM_VF_PARTIAL,&vcc->flags); 424 clear_bit(ATM_VF_PARTIAL, &vcc->flags);
426 else 425 else
427 if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) 426 if (test_bit(ATM_VF_PARTIAL, &vcc->flags))
428 return -EINVAL; 427 return -EINVAL;
429 pr_debug("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; " 428 pr_debug("(TX: cl %d,bw %d-%d,sdu %d; "
430 "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",
431 vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, 430 vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,
432 vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, 431 vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu,
433 vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr, 432 vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr,
434 vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, 433 vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_sdu,
435 vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : 434 vcc->qos.aal == ATM_AAL5 ? "" :
436 " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); 435 vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ",
436 vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
437 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) 437 if (!test_bit(ATM_VF_HASQOS, &vcc->flags))
438 return -EBADFD; 438 return -EBADFD;
439 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || 439 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
440 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) 440 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
441 return -EINVAL; 441 return -EINVAL;
442 if (likely(itf != ATM_ITF_ANY)) { 442 if (likely(itf != ATM_ITF_ANY)) {
443 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);
444 } else { 445 } else {
445 dev = NULL; 446 dev = NULL;
446 mutex_lock(&atm_dev_mutex); 447 mutex_lock(&atm_dev_mutex);
447 if (!list_empty(&atm_devs)) { 448 if (!list_empty(&atm_devs)) {
448 dev = list_entry(atm_devs.next, struct atm_dev, dev_list); 449 dev = list_entry(atm_devs.next,
450 struct atm_dev, dev_list);
449 atm_dev_hold(dev); 451 atm_dev_hold(dev);
450 } 452 }
451 mutex_unlock(&atm_dev_mutex); 453 mutex_unlock(&atm_dev_mutex);
@@ -458,13 +460,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
458 return error; 460 return error;
459 } 461 }
460 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) 462 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
461 set_bit(ATM_VF_PARTIAL,&vcc->flags); 463 set_bit(ATM_VF_PARTIAL, &vcc->flags);
462 if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags)) 464 if (test_bit(ATM_VF_READY, &ATM_SD(sock)->flags))
463 sock->state = SS_CONNECTED; 465 sock->state = SS_CONNECTED;
464 return 0; 466 return 0;
465} 467}
466 468
467
468int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, 469int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
469 size_t size, int flags) 470 size_t size, int flags)
470{ 471{
@@ -478,8 +479,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
478 if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */ 479 if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */
479 return -EOPNOTSUPP; 480 return -EOPNOTSUPP;
480 vcc = ATM_SD(sock); 481 vcc = ATM_SD(sock);
481 if (test_bit(ATM_VF_RELEASED,&vcc->flags) || 482 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
482 test_bit(ATM_VF_CLOSE,&vcc->flags) || 483 test_bit(ATM_VF_CLOSE, &vcc->flags) ||
483 !test_bit(ATM_VF_READY, &vcc->flags)) 484 !test_bit(ATM_VF_READY, &vcc->flags))
484 return 0; 485 return 0;
485 486
@@ -497,13 +498,12 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
497 if (error) 498 if (error)
498 return error; 499 return error;
499 sock_recv_ts_and_drops(msg, sk, skb); 500 sock_recv_ts_and_drops(msg, sk, skb);
500 pr_debug("RcvM %d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize); 501 pr_debug("%d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize);
501 atm_return(vcc, skb->truesize); 502 atm_return(vcc, skb->truesize);
502 skb_free_datagram(sk, skb); 503 skb_free_datagram(sk, skb);
503 return copied; 504 return copied;
504} 505}
505 506
506
507int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, 507int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
508 size_t total_len) 508 size_t total_len)
509{ 509{
@@ -511,7 +511,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
511 DEFINE_WAIT(wait); 511 DEFINE_WAIT(wait);
512 struct atm_vcc *vcc; 512 struct atm_vcc *vcc;
513 struct sk_buff *skb; 513 struct sk_buff *skb;
514 int eff,error; 514 int eff, error;
515 const void __user *buff; 515 const void __user *buff;
516 int size; 516 int size;
517 517
@@ -550,7 +550,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
550 eff = (size+3) & ~3; /* align to word boundary */ 550 eff = (size+3) & ~3; /* align to word boundary */
551 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); 551 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
552 error = 0; 552 error = 0;
553 while (!(skb = alloc_tx(vcc,eff))) { 553 while (!(skb = alloc_tx(vcc, eff))) {
554 if (m->msg_flags & MSG_DONTWAIT) { 554 if (m->msg_flags & MSG_DONTWAIT) {
555 error = -EAGAIN; 555 error = -EAGAIN;
556 break; 556 break;
@@ -560,9 +560,9 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
560 error = -ERESTARTSYS; 560 error = -ERESTARTSYS;
561 break; 561 break;
562 } 562 }
563 if (test_bit(ATM_VF_RELEASED,&vcc->flags) || 563 if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
564 test_bit(ATM_VF_CLOSE,&vcc->flags) || 564 test_bit(ATM_VF_CLOSE, &vcc->flags) ||
565 !test_bit(ATM_VF_READY,&vcc->flags)) { 565 !test_bit(ATM_VF_READY, &vcc->flags)) {
566 error = -EPIPE; 566 error = -EPIPE;
567 send_sig(SIGPIPE, current, 0); 567 send_sig(SIGPIPE, current, 0);
568 break; 568 break;
@@ -574,20 +574,20 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
574 goto out; 574 goto out;
575 skb->dev = NULL; /* for paths shared with net_device interfaces */ 575 skb->dev = NULL; /* for paths shared with net_device interfaces */
576 ATM_SKB(skb)->atm_options = vcc->atm_options; 576 ATM_SKB(skb)->atm_options = vcc->atm_options;
577 if (copy_from_user(skb_put(skb,size),buff,size)) { 577 if (copy_from_user(skb_put(skb, size), buff, size)) {
578 kfree_skb(skb); 578 kfree_skb(skb);
579 error = -EFAULT; 579 error = -EFAULT;
580 goto out; 580 goto out;
581 } 581 }
582 if (eff != size) memset(skb->data+size,0,eff-size); 582 if (eff != size)
583 error = vcc->dev->ops->send(vcc,skb); 583 memset(skb->data + size, 0, eff-size);
584 error = vcc->dev->ops->send(vcc, skb);
584 error = error ? error : size; 585 error = error ? error : size;
585out: 586out:
586 release_sock(sk); 587 release_sock(sk);
587 return error; 588 return error;
588} 589}
589 590
590
591unsigned 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)
592{ 592{
593 struct sock *sk = sock->sk; 593 struct sock *sk = sock->sk;
@@ -623,8 +623,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
623 return mask; 623 return mask;
624} 624}
625 625
626 626static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
627static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
628{ 627{
629 int error; 628 int error;
630 629
@@ -636,25 +635,31 @@ static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
636 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || 635 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
637 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) 636 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
638 return -EINVAL; 637 return -EINVAL;
639 error = adjust_tp(&qos->txtp,qos->aal); 638 error = adjust_tp(&qos->txtp, qos->aal);
640 if (!error) error = adjust_tp(&qos->rxtp,qos->aal); 639 if (!error)
641 if (error) return error; 640 error = adjust_tp(&qos->rxtp, qos->aal);
642 if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; 641 if (error)
642 return error;
643 if (!vcc->dev->ops->change_qos)
644 return -EOPNOTSUPP;
643 if (sk_atm(vcc)->sk_family == AF_ATMPVC) 645 if (sk_atm(vcc)->sk_family == AF_ATMPVC)
644 return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); 646 return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
645 return svc_change_qos(vcc,qos); 647 return svc_change_qos(vcc, qos);
646} 648}
647 649
648
649static int check_tp(const struct atm_trafprm *tp) 650static int check_tp(const struct atm_trafprm *tp)
650{ 651{
651 /* @@@ Should be merged with adjust_tp */ 652 /* @@@ Should be merged with adjust_tp */
652 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0; 653 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS)
654 return 0;
653 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr && 655 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
654 !tp->max_pcr) return -EINVAL; 656 !tp->max_pcr)
655 if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL; 657 return -EINVAL;
658 if (tp->min_pcr == ATM_MAX_PCR)
659 return -EINVAL;
656 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 &&
657 tp->min_pcr > tp->max_pcr) return -EINVAL; 661 tp->min_pcr > tp->max_pcr)
662 return -EINVAL;
658 /* 663 /*
659 * 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
660 * adjustment may still push it in the valid range. 665 * adjustment may still push it in the valid range.
@@ -662,7 +667,6 @@ static int check_tp(const struct atm_trafprm *tp)
662 return 0; 667 return 0;
663} 668}
664 669
665
666static int check_qos(const struct atm_qos *qos) 670static int check_qos(const struct atm_qos *qos)
667{ 671{
668 int error; 672 int error;
@@ -672,9 +676,11 @@ static int check_qos(const struct atm_qos *qos)
672 if (qos->txtp.traffic_class != qos->rxtp.traffic_class && 676 if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
673 qos->txtp.traffic_class && qos->rxtp.traffic_class && 677 qos->txtp.traffic_class && qos->rxtp.traffic_class &&
674 qos->txtp.traffic_class != ATM_ANYCLASS && 678 qos->txtp.traffic_class != ATM_ANYCLASS &&
675 qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL; 679 qos->rxtp.traffic_class != ATM_ANYCLASS)
680 return -EINVAL;
676 error = check_tp(&qos->txtp); 681 error = check_tp(&qos->txtp);
677 if (error) return error; 682 if (error)
683 return error;
678 return check_tp(&qos->rxtp); 684 return check_tp(&qos->rxtp);
679} 685}
680 686
@@ -690,37 +696,41 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
690 696
691 vcc = ATM_SD(sock); 697 vcc = ATM_SD(sock);
692 switch (optname) { 698 switch (optname) {
693 case SO_ATMQOS: 699 case SO_ATMQOS:
694 { 700 {
695 struct atm_qos qos; 701 struct atm_qos qos;
696 702
697 if (copy_from_user(&qos,optval,sizeof(qos))) 703 if (copy_from_user(&qos, optval, sizeof(qos)))
698 return -EFAULT; 704 return -EFAULT;
699 error = check_qos(&qos); 705 error = check_qos(&qos);
700 if (error) return error; 706 if (error)
701 if (sock->state == SS_CONNECTED) 707 return error;
702 return atm_change_qos(vcc,&qos); 708 if (sock->state == SS_CONNECTED)
703 if (sock->state != SS_UNCONNECTED) 709 return atm_change_qos(vcc, &qos);
704 return -EBADFD; 710 if (sock->state != SS_UNCONNECTED)
705 vcc->qos = qos; 711 return -EBADFD;
706 set_bit(ATM_VF_HASQOS,&vcc->flags); 712 vcc->qos = qos;
707 return 0; 713 set_bit(ATM_VF_HASQOS, &vcc->flags);
708 } 714 return 0;
709 case SO_SETCLP:
710 if (get_user(value,(unsigned long __user *)optval))
711 return -EFAULT;
712 if (value) vcc->atm_options |= ATM_ATMOPT_CLP;
713 else vcc->atm_options &= ~ATM_ATMOPT_CLP;
714 return 0;
715 default:
716 if (level == SOL_SOCKET) return -EINVAL;
717 break;
718 } 715 }
719 if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL; 716 case SO_SETCLP:
720 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);
721} 732}
722 733
723
724int vcc_getsockopt(struct socket *sock, int level, int optname, 734int vcc_getsockopt(struct socket *sock, int level, int optname,
725 char __user *optval, int __user *optlen) 735 char __user *optval, int __user *optlen)
726{ 736{
@@ -734,33 +744,33 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,
734 744
735 vcc = ATM_SD(sock); 745 vcc = ATM_SD(sock);
736 switch (optname) { 746 switch (optname) {
737 case SO_ATMQOS: 747 case SO_ATMQOS:
738 if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) 748 if (!test_bit(ATM_VF_HASQOS, &vcc->flags))
739 return -EINVAL; 749 return -EINVAL;
740 return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ? 750 return copy_to_user(optval, &vcc->qos, sizeof(vcc->qos))
741 -EFAULT : 0; 751 ? -EFAULT : 0;
742 case SO_SETCLP: 752 case SO_SETCLP:
743 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 753 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0,
744 0,(unsigned long __user *)optval) ? -EFAULT : 0; 754 (unsigned long __user *)optval) ? -EFAULT : 0;
745 case SO_ATMPVC: 755 case SO_ATMPVC:
746 { 756 {
747 struct sockaddr_atmpvc pvc; 757 struct sockaddr_atmpvc pvc;
748 758
749 if (!vcc->dev || 759 if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))
750 !test_bit(ATM_VF_ADDR,&vcc->flags)) 760 return -ENOTCONN;
751 return -ENOTCONN; 761 pvc.sap_family = AF_ATMPVC;
752 pvc.sap_family = AF_ATMPVC; 762 pvc.sap_addr.itf = vcc->dev->number;
753 pvc.sap_addr.itf = vcc->dev->number; 763 pvc.sap_addr.vpi = vcc->vpi;
754 pvc.sap_addr.vpi = vcc->vpi; 764 pvc.sap_addr.vci = vcc->vci;
755 pvc.sap_addr.vci = vcc->vci; 765 return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0;
756 return copy_to_user(optval,&pvc,sizeof(pvc)) ? 766 }
757 -EFAULT : 0; 767 default:
758 } 768 if (level == SOL_SOCKET)
759 default: 769 return -EINVAL;
760 if (level == SOL_SOCKET) return -EINVAL;
761 break; 770 break;
762 } 771 }
763 if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; 772 if (!vcc->dev || !vcc->dev->ops->getsockopt)
773 return -EINVAL;
764 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); 774 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
765} 775}
766 776
@@ -768,23 +778,27 @@ static int __init atm_init(void)
768{ 778{
769 int error; 779 int error;
770 780
771 if ((error = proto_register(&vcc_proto, 0)) < 0) 781 error = proto_register(&vcc_proto, 0);
782 if (error < 0)
772 goto out; 783 goto out;
773 784 error = atmpvc_init();
774 if ((error = atmpvc_init()) < 0) { 785 if (error < 0) {
775 printk(KERN_ERR "atmpvc_init() failed with %d\n", error); 786 pr_err("atmpvc_init() failed with %d\n", error);
776 goto out_unregister_vcc_proto; 787 goto out_unregister_vcc_proto;
777 } 788 }
778 if ((error = atmsvc_init()) < 0) { 789 error = atmsvc_init();
779 printk(KERN_ERR "atmsvc_init() failed with %d\n", error); 790 if (error < 0) {
791 pr_err("atmsvc_init() failed with %d\n", error);
780 goto out_atmpvc_exit; 792 goto out_atmpvc_exit;
781 } 793 }
782 if ((error = atm_proc_init()) < 0) { 794 error = atm_proc_init();
783 printk(KERN_ERR "atm_proc_init() failed with %d\n",error); 795 if (error < 0) {
796 pr_err("atm_proc_init() failed with %d\n", error);
784 goto out_atmsvc_exit; 797 goto out_atmsvc_exit;
785 } 798 }
786 if ((error = atm_sysfs_init()) < 0) { 799 error = atm_sysfs_init();
787 printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error); 800 if (error < 0) {
801 pr_err("atm_sysfs_init() failed with %d\n", error);
788 goto out_atmproc_exit; 802 goto out_atmproc_exit;
789 } 803 }
790out: 804out: