+static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
+ int sockaddr_len, int flags)
+{
+ DEFINE_WAIT(wait);
+ struct sock *sk = sock->sk;
+ struct atm_vcc *vcc = ATM_SD(sock);
+ int error;
+
+ lock_sock(sk);
+ set_bit(ATM_VF_WAITING, &vcc->flags);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ sigd_enq(vcc, as_addparty, NULL, NULL,
+ (struct sockaddr_atmsvc *) sockaddr);
+ if (flags & O_NONBLOCK) {
+ finish_wait(sk->sk_sleep, &wait);
+ error = -EINPROGRESS;
+ goto out;
+ }
+ DPRINTK("svc_addparty added wait queue\n");
+ while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
+ schedule();
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ }
+ finish_wait(sk->sk_sleep, &wait);
+ error = xchg(&sk->sk_err_soft, 0);
+out:
+ release_sock(sk);
+ return error;
+}
+
+
+static int svc_dropparty(struct socket *sock, int ep_ref)
+{
+ DEFINE_WAIT(wait);
+ struct sock *sk = sock->sk;
+ struct atm_vcc *vcc = ATM_SD(sock);
+ int error;
+
+ lock_sock(sk);
+ set_bit(ATM_VF_WAITING, &vcc->flags);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
+ while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
+ schedule();
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ }
+ finish_wait(sk->sk_sleep, &wait);
+ if (!sigd) {
+ error = -EUNATCH;
+ goto out;
+ }
+ error = xchg(&sk->sk_err_soft, 0);
+out:
+ release_sock(sk);
+ return error;
+}
+
+
+static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ int error, ep_ref;
+ struct sockaddr_atmsvc sa;
+ struct atm_vcc *vcc = ATM_SD(sock);
+
+ switch (cmd) {
+ case ATM_ADDPARTY:
+ if (!test_bit(ATM_VF_SESSION, &vcc->flags))
+ return -EINVAL;
+ if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
+ return -EFAULT;
+ error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0);
+ break;
+ case ATM_DROPPARTY:
+ if (!test_bit(ATM_VF_SESSION, &vcc->flags))
+ return -EINVAL;
+ if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
+ return -EFAULT;
+ error = svc_dropparty(sock, ep_ref);
+ break;
+ default:
+ error = vcc_ioctl(sock, cmd, arg);
+ }
+
+ return error;
+}
+
+static const struct proto_ops svc_proto_ops = {