Lines Matching +full:vcc +full:- +full:p
1 /* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
17 #include <linux/time64.h> /* 64-bit time for seconds */
44 struct atm_vcc *vcc = atm_sk(sk); in __vcc_insert_socket() local
45 struct hlist_head *head = &vcc_hash[vcc->vci & (VCC_HTABLE_SIZE - 1)]; in __vcc_insert_socket()
46 sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); in __vcc_insert_socket()
65 static bool vcc_tx_ready(struct atm_vcc *vcc, unsigned int size) in vcc_tx_ready() argument
67 struct sock *sk = sk_atm(vcc); in vcc_tx_ready()
69 if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { in vcc_tx_ready()
71 sk_wmem_alloc_get(sk), size, sk->sk_sndbuf); in vcc_tx_ready()
79 if (atomic_read(&sk->sk_rmem_alloc)) in vcc_sock_destruct()
81 __func__, atomic_read(&sk->sk_rmem_alloc)); in vcc_sock_destruct()
83 if (refcount_read(&sk->sk_wmem_alloc)) in vcc_sock_destruct()
85 __func__, refcount_read(&sk->sk_wmem_alloc)); in vcc_sock_destruct()
93 wq = rcu_dereference(sk->sk_wq); in vcc_def_wakeup()
95 wake_up(&wq->wait); in vcc_def_wakeup()
101 struct atm_vcc *vcc = atm_sk(sk); in vcc_writable() local
103 return (vcc->qos.txtp.max_sdu + in vcc_writable()
104 refcount_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf; in vcc_writable()
114 wq = rcu_dereference(sk->sk_wq); in vcc_write_space()
116 wake_up_interruptible(&wq->wait); in vcc_write_space()
126 struct atm_vcc *vcc = atm_sk(sk); in vcc_release_cb() local
128 if (vcc->release_cb) in vcc_release_cb()
129 vcc->release_cb(vcc); in vcc_release_cb()
133 .name = "VCC",
142 struct atm_vcc *vcc; in vcc_create() local
144 sock->sk = NULL; in vcc_create()
145 if (sock->type == SOCK_STREAM) in vcc_create()
146 return -EINVAL; in vcc_create()
149 return -ENOMEM; in vcc_create()
151 sk->sk_state_change = vcc_def_wakeup; in vcc_create()
152 sk->sk_write_space = vcc_write_space; in vcc_create()
154 vcc = atm_sk(sk); in vcc_create()
155 vcc->dev = NULL; in vcc_create()
156 memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc)); in vcc_create()
157 memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc)); in vcc_create()
158 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ in vcc_create()
159 refcount_set(&sk->sk_wmem_alloc, 1); in vcc_create()
160 atomic_set(&sk->sk_rmem_alloc, 0); in vcc_create()
161 vcc->push = NULL; in vcc_create()
162 vcc->pop = NULL; in vcc_create()
163 vcc->owner = NULL; in vcc_create()
164 vcc->push_oam = NULL; in vcc_create()
165 vcc->release_cb = NULL; in vcc_create()
166 vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */ in vcc_create()
167 vcc->atm_options = vcc->aal_options = 0; in vcc_create()
168 sk->sk_destruct = vcc_sock_destruct; in vcc_create()
174 struct atm_vcc *vcc = atm_sk(sk); in vcc_destroy_socket() local
177 set_bit(ATM_VF_CLOSE, &vcc->flags); in vcc_destroy_socket()
178 clear_bit(ATM_VF_READY, &vcc->flags); in vcc_destroy_socket()
179 if (vcc->dev) { in vcc_destroy_socket()
180 if (vcc->dev->ops->close) in vcc_destroy_socket()
181 vcc->dev->ops->close(vcc); in vcc_destroy_socket()
182 if (vcc->push) in vcc_destroy_socket()
183 vcc->push(vcc, NULL); /* atmarpd has no push */ in vcc_destroy_socket()
184 module_put(vcc->owner); in vcc_destroy_socket()
186 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { in vcc_destroy_socket()
187 atm_return(vcc, skb->truesize); in vcc_destroy_socket()
191 module_put(vcc->dev->ops->owner); in vcc_destroy_socket()
192 atm_dev_put(vcc->dev); in vcc_destroy_socket()
200 struct sock *sk = sock->sk; in vcc_release()
204 vcc_destroy_socket(sock->sk); in vcc_release()
212 void vcc_release_async(struct atm_vcc *vcc, int reply) in vcc_release_async() argument
214 struct sock *sk = sk_atm(vcc); in vcc_release_async()
216 set_bit(ATM_VF_CLOSE, &vcc->flags); in vcc_release_async()
217 sk->sk_shutdown |= RCV_SHUTDOWN; in vcc_release_async()
218 sk->sk_err = -reply; in vcc_release_async()
219 clear_bit(ATM_VF_WAITING, &vcc->flags); in vcc_release_async()
220 sk->sk_state_change(sk); in vcc_release_async()
224 void vcc_process_recv_queue(struct atm_vcc *vcc) in vcc_process_recv_queue() argument
231 rq = &sk_atm(vcc)->sk_receive_queue; in vcc_process_recv_queue()
233 spin_lock_irqsave(&rq->lock, flags); in vcc_process_recv_queue()
235 spin_unlock_irqrestore(&rq->lock, flags); in vcc_process_recv_queue()
239 vcc->push(vcc, skb); in vcc_process_recv_queue()
246 pr_debug("%s signal=%d dev=%p number=%d dev->signal=%d\n", in atm_dev_signal_change()
247 __func__, signal, dev, dev->number, dev->signal); in atm_dev_signal_change()
252 if (dev->signal == signal) in atm_dev_signal_change()
255 dev->signal = signal; in atm_dev_signal_change()
270 struct atm_vcc *vcc; in atm_dev_release_vccs() local
273 vcc = atm_sk(s); in atm_dev_release_vccs()
274 if (vcc->dev == dev) { in atm_dev_release_vccs()
275 vcc_release_async(vcc, -EPIPE); in atm_dev_release_vccs()
288 if (!tp->traffic_class) in adjust_tp()
292 max_sdu = ATM_CELL_SIZE-1; in adjust_tp()
303 if (!tp->max_sdu) in adjust_tp()
304 tp->max_sdu = max_sdu; in adjust_tp()
305 else if (tp->max_sdu > max_sdu) in adjust_tp()
306 return -EINVAL; in adjust_tp()
307 if (!tp->max_cdv) in adjust_tp()
308 tp->max_cdv = ATM_MAX_CDV; in adjust_tp()
312 static int check_ci(const struct atm_vcc *vcc, short vpi, int vci) in check_ci() argument
314 struct hlist_head *head = &vcc_hash[vci & (VCC_HTABLE_SIZE - 1)]; in check_ci()
320 if (walk->dev != vcc->dev) in check_ci()
322 if (test_bit(ATM_VF_ADDR, &walk->flags) && walk->vpi == vpi && in check_ci()
323 walk->vci == vci && ((walk->qos.txtp.traffic_class != in check_ci()
324 ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) || in check_ci()
325 (walk->qos.rxtp.traffic_class != ATM_NONE && in check_ci()
326 vcc->qos.rxtp.traffic_class != ATM_NONE))) in check_ci()
327 return -EADDRINUSE; in check_ci()
337 static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci) in find_ci() argument
339 static short p; /* poor man's per-device cache */ in find_ci() local
346 err = check_ci(vcc, *vpi, *vci); in find_ci()
351 p = *vpi; in find_ci()
352 else if (p >= 1 << vcc->dev->ci_range.vpi_bits) in find_ci()
353 p = 0; in find_ci()
356 else if (c < ATM_NOT_RSV_VCI || c >= 1 << vcc->dev->ci_range.vci_bits) in find_ci()
358 old_p = p; in find_ci()
361 if (!check_ci(vcc, p, c)) { in find_ci()
362 *vpi = p; in find_ci()
368 if (c >= 1 << vcc->dev->ci_range.vci_bits) in find_ci()
373 p++; in find_ci()
374 if (p >= 1 << vcc->dev->ci_range.vpi_bits) in find_ci()
375 p = 0; in find_ci()
377 } while (old_p != p || old_c != c); in find_ci()
378 return -EADDRINUSE; in find_ci()
381 static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, in __vcc_connect() argument
384 struct sock *sk = sk_atm(vcc); in __vcc_connect()
388 vpi >> dev->ci_range.vpi_bits) || (vci != ATM_VCI_UNSPEC && in __vcc_connect()
389 vci != ATM_VCI_ANY && vci >> dev->ci_range.vci_bits)) in __vcc_connect()
390 return -EINVAL; in __vcc_connect()
392 return -EPERM; in __vcc_connect()
393 error = -ENODEV; in __vcc_connect()
394 if (!try_module_get(dev->ops->owner)) in __vcc_connect()
396 vcc->dev = dev; in __vcc_connect()
398 if (test_bit(ATM_DF_REMOVED, &dev->flags) || in __vcc_connect()
399 (error = find_ci(vcc, &vpi, &vci))) { in __vcc_connect()
403 vcc->vpi = vpi; in __vcc_connect()
404 vcc->vci = vci; in __vcc_connect()
407 switch (vcc->qos.aal) { in __vcc_connect()
409 error = atm_init_aal0(vcc); in __vcc_connect()
410 vcc->stats = &dev->stats.aal0; in __vcc_connect()
413 error = atm_init_aal34(vcc); in __vcc_connect()
414 vcc->stats = &dev->stats.aal34; in __vcc_connect()
418 vcc->qos.aal = ATM_AAL5; in __vcc_connect()
421 error = atm_init_aal5(vcc); in __vcc_connect()
422 vcc->stats = &dev->stats.aal5; in __vcc_connect()
425 error = -EPROTOTYPE; in __vcc_connect()
428 error = adjust_tp(&vcc->qos.txtp, vcc->qos.aal); in __vcc_connect()
430 error = adjust_tp(&vcc->qos.rxtp, vcc->qos.aal); in __vcc_connect()
433 pr_debug("VCC %d.%d, AAL %d\n", vpi, vci, vcc->qos.aal); in __vcc_connect()
435 vcc->qos.txtp.traffic_class, in __vcc_connect()
436 vcc->qos.txtp.min_pcr, in __vcc_connect()
437 vcc->qos.txtp.max_pcr, in __vcc_connect()
438 vcc->qos.txtp.max_sdu); in __vcc_connect()
440 vcc->qos.rxtp.traffic_class, in __vcc_connect()
441 vcc->qos.rxtp.min_pcr, in __vcc_connect()
442 vcc->qos.rxtp.max_pcr, in __vcc_connect()
443 vcc->qos.rxtp.max_sdu); in __vcc_connect()
445 if (dev->ops->open) { in __vcc_connect()
446 error = dev->ops->open(vcc); in __vcc_connect()
455 module_put(dev->ops->owner); in __vcc_connect()
457 vcc->dev = NULL; in __vcc_connect()
464 struct atm_vcc *vcc = ATM_SD(sock); in vcc_connect() local
468 if (sock->state == SS_CONNECTED) in vcc_connect()
469 return -EISCONN; in vcc_connect()
470 if (sock->state != SS_UNCONNECTED) in vcc_connect()
471 return -EINVAL; in vcc_connect()
473 return -EINVAL; in vcc_connect()
476 clear_bit(ATM_VF_PARTIAL, &vcc->flags); in vcc_connect()
478 if (test_bit(ATM_VF_PARTIAL, &vcc->flags)) in vcc_connect()
479 return -EINVAL; in vcc_connect()
480 pr_debug("(TX: cl %d,bw %d-%d,sdu %d; " in vcc_connect()
481 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", in vcc_connect()
482 vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr, in vcc_connect()
483 vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu, in vcc_connect()
484 vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr, in vcc_connect()
485 vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_sdu, in vcc_connect()
486 vcc->qos.aal == ATM_AAL5 ? "" : in vcc_connect()
487 vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ", in vcc_connect()
488 vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); in vcc_connect()
489 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) in vcc_connect()
490 return -EBADFD; in vcc_connect()
491 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || in vcc_connect()
492 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) in vcc_connect()
493 return -EINVAL; in vcc_connect()
496 "atm-device-%d", itf); in vcc_connect()
508 return -ENODEV; in vcc_connect()
509 error = __vcc_connect(vcc, dev, vpi, vci); in vcc_connect()
515 set_bit(ATM_VF_PARTIAL, &vcc->flags); in vcc_connect()
516 if (test_bit(ATM_VF_READY, &ATM_SD(sock)->flags)) in vcc_connect()
517 sock->state = SS_CONNECTED; in vcc_connect()
524 struct sock *sk = sock->sk; in vcc_recvmsg()
525 struct atm_vcc *vcc; in vcc_recvmsg() local
527 int copied, error = -EINVAL; in vcc_recvmsg()
529 if (sock->state != SS_CONNECTED) in vcc_recvmsg()
530 return -ENOTCONN; in vcc_recvmsg()
534 return -EOPNOTSUPP; in vcc_recvmsg()
536 vcc = ATM_SD(sock); in vcc_recvmsg()
537 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || in vcc_recvmsg()
538 test_bit(ATM_VF_CLOSE, &vcc->flags) || in vcc_recvmsg()
539 !test_bit(ATM_VF_READY, &vcc->flags)) in vcc_recvmsg()
546 copied = skb->len; in vcc_recvmsg()
549 msg->msg_flags |= MSG_TRUNC; in vcc_recvmsg()
558 pr_debug("%d -= %d\n", atomic_read(&sk->sk_rmem_alloc), in vcc_recvmsg()
559 skb->truesize); in vcc_recvmsg()
560 atm_return(vcc, skb->truesize); in vcc_recvmsg()
569 struct sock *sk = sock->sk; in vcc_sendmsg()
571 struct atm_vcc *vcc; in vcc_sendmsg() local
576 if (sock->state != SS_CONNECTED) { in vcc_sendmsg()
577 error = -ENOTCONN; in vcc_sendmsg()
580 if (m->msg_name) { in vcc_sendmsg()
581 error = -EISCONN; in vcc_sendmsg()
584 vcc = ATM_SD(sock); in vcc_sendmsg()
585 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || in vcc_sendmsg()
586 test_bit(ATM_VF_CLOSE, &vcc->flags) || in vcc_sendmsg()
587 !test_bit(ATM_VF_READY, &vcc->flags)) { in vcc_sendmsg()
588 error = -EPIPE; in vcc_sendmsg()
596 if (size > vcc->qos.txtp.max_sdu) { in vcc_sendmsg()
597 error = -EMSGSIZE; in vcc_sendmsg()
604 while (!vcc_tx_ready(vcc, eff)) { in vcc_sendmsg()
605 if (m->msg_flags & MSG_DONTWAIT) { in vcc_sendmsg()
606 error = -EAGAIN; in vcc_sendmsg()
611 error = -ERESTARTSYS; in vcc_sendmsg()
614 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || in vcc_sendmsg()
615 test_bit(ATM_VF_CLOSE, &vcc->flags) || in vcc_sendmsg()
616 !test_bit(ATM_VF_READY, &vcc->flags)) { in vcc_sendmsg()
617 error = -EPIPE; in vcc_sendmsg()
629 error = -ENOMEM; in vcc_sendmsg()
632 pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); in vcc_sendmsg()
633 atm_account_tx(vcc, skb); in vcc_sendmsg()
635 skb->dev = NULL; /* for paths shared with net_device interfaces */ in vcc_sendmsg()
636 if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { in vcc_sendmsg()
638 error = -EFAULT; in vcc_sendmsg()
642 memset(skb->data + size, 0, eff-size); in vcc_sendmsg()
643 error = vcc->dev->ops->send(vcc, skb); in vcc_sendmsg()
652 struct sock *sk = sock->sk; in vcc_poll()
653 struct atm_vcc *vcc; in vcc_poll() local
659 vcc = ATM_SD(sock); in vcc_poll()
662 if (sk->sk_err) in vcc_poll()
665 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || in vcc_poll()
666 test_bit(ATM_VF_CLOSE, &vcc->flags)) in vcc_poll()
670 if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) in vcc_poll()
674 if (sock->state == SS_CONNECTING && in vcc_poll()
675 test_bit(ATM_VF_WAITING, &vcc->flags)) in vcc_poll()
678 if (vcc->qos.txtp.traffic_class != ATM_NONE && in vcc_poll()
685 static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) in atm_change_qos() argument
693 if (qos->aal != vcc->qos.aal || in atm_change_qos()
694 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || in atm_change_qos()
695 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) in atm_change_qos()
696 return -EINVAL; in atm_change_qos()
697 error = adjust_tp(&qos->txtp, qos->aal); in atm_change_qos()
699 error = adjust_tp(&qos->rxtp, qos->aal); in atm_change_qos()
702 if (!vcc->dev->ops->change_qos) in atm_change_qos()
703 return -EOPNOTSUPP; in atm_change_qos()
704 if (sk_atm(vcc)->sk_family == AF_ATMPVC) in atm_change_qos()
705 return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET); in atm_change_qos()
706 return svc_change_qos(vcc, qos); in atm_change_qos()
712 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) in check_tp()
714 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr && in check_tp()
715 !tp->max_pcr) in check_tp()
716 return -EINVAL; in check_tp()
717 if (tp->min_pcr == ATM_MAX_PCR) in check_tp()
718 return -EINVAL; in check_tp()
719 if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR && in check_tp()
720 tp->min_pcr > tp->max_pcr) in check_tp()
721 return -EINVAL; in check_tp()
733 if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class) in check_qos()
734 return -EINVAL; in check_qos()
735 if (qos->txtp.traffic_class != qos->rxtp.traffic_class && in check_qos()
736 qos->txtp.traffic_class && qos->rxtp.traffic_class && in check_qos()
737 qos->txtp.traffic_class != ATM_ANYCLASS && in check_qos()
738 qos->rxtp.traffic_class != ATM_ANYCLASS) in check_qos()
739 return -EINVAL; in check_qos()
740 error = check_tp(&qos->txtp); in check_qos()
743 return check_tp(&qos->rxtp); in check_qos()
749 struct atm_vcc *vcc; in vcc_setsockopt() local
754 return -EINVAL; in vcc_setsockopt()
756 vcc = ATM_SD(sock); in vcc_setsockopt()
763 return -EFAULT; in vcc_setsockopt()
767 if (sock->state == SS_CONNECTED) in vcc_setsockopt()
768 return atm_change_qos(vcc, &qos); in vcc_setsockopt()
769 if (sock->state != SS_UNCONNECTED) in vcc_setsockopt()
770 return -EBADFD; in vcc_setsockopt()
771 vcc->qos = qos; in vcc_setsockopt()
772 set_bit(ATM_VF_HASQOS, &vcc->flags); in vcc_setsockopt()
777 return -EFAULT; in vcc_setsockopt()
779 vcc->atm_options |= ATM_ATMOPT_CLP; in vcc_setsockopt()
781 vcc->atm_options &= ~ATM_ATMOPT_CLP; in vcc_setsockopt()
785 return -EINVAL; in vcc_setsockopt()
788 if (!vcc->dev || !vcc->dev->ops->setsockopt) in vcc_setsockopt()
789 return -EINVAL; in vcc_setsockopt()
790 return vcc->dev->ops->setsockopt(vcc, level, optname, optval, optlen); in vcc_setsockopt()
796 struct atm_vcc *vcc; in vcc_getsockopt() local
800 return -EFAULT; in vcc_getsockopt()
802 return -EINVAL; in vcc_getsockopt()
804 vcc = ATM_SD(sock); in vcc_getsockopt()
807 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) in vcc_getsockopt()
808 return -EINVAL; in vcc_getsockopt()
809 return copy_to_user(optval, &vcc->qos, sizeof(vcc->qos)) in vcc_getsockopt()
810 ? -EFAULT : 0; in vcc_getsockopt()
812 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0, in vcc_getsockopt()
813 (unsigned long __user *)optval) ? -EFAULT : 0; in vcc_getsockopt()
818 if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) in vcc_getsockopt()
819 return -ENOTCONN; in vcc_getsockopt()
822 pvc.sap_addr.itf = vcc->dev->number; in vcc_getsockopt()
823 pvc.sap_addr.vpi = vcc->vpi; in vcc_getsockopt()
824 pvc.sap_addr.vci = vcc->vci; in vcc_getsockopt()
825 return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0; in vcc_getsockopt()
829 return -EINVAL; in vcc_getsockopt()
832 if (!vcc->dev || !vcc->dev->ops->getsockopt) in vcc_getsockopt()
833 return -EINVAL; in vcc_getsockopt()
834 return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); in vcc_getsockopt()