• Home
  • Raw
  • Download

Lines Matching +full:vcc +full:- +full:p

1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* net/atm/pppoatm.c - RFC2364 PPP over ATM/AAL5 */
4 /* Copyright 1999-2000 by Mitchell Blank Jr */
5 /* Based on clip.c; 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
17 * section 8 of RFC2364 - we are supposed to detect a change
19 * to avoid a black-hole being created if our peer loses state
24 * 1. LLC-encapsulation was missing when it was enabled. In
27 * 2. LLC-encapsulation was present when it was disabled. Then
44 #include <linux/ppp-ioctl.h>
57 struct atm_vcc *atmvcc; /* VCC descriptor */
66 int flags; /* SC_COMP_PROT - compress protocol */
75 * inflight == -2 represents an empty queue, -1 one packet, and zero means
78 #define NONE_INFLIGHT -2
91 return (struct pppoatm_vcc *) (atmvcc->user_back); in atmvcc_to_pvcc()
96 return (struct pppoatm_vcc *) (chan->private); in chan_to_pvcc()
116 * channel's ->downl lock. And the potential race with *setting* it, in pppoatm_release_cb()
117 * which leads to the double-check dance in pppoatm_may_send(), doesn't in pppoatm_release_cb()
120 * ->release_cb() can't be called until that's done. in pppoatm_release_cb()
122 if (test_and_clear_bit(BLOCKED, &pvcc->blocked)) in pppoatm_release_cb()
123 tasklet_schedule(&pvcc->wakeup_tasklet); in pppoatm_release_cb()
124 if (pvcc->old_release_cb) in pppoatm_release_cb()
125 pvcc->old_release_cb(atmvcc); in pppoatm_release_cb()
129 * skb. The ->old_pop will take care up normal atm flow control,
136 pvcc->old_pop(atmvcc, skb); in pppoatm_pop()
137 atomic_dec(&pvcc->inflight); in pppoatm_pop()
145 * while holding the channel->downl lock. And ppp_output_wakeup() as in pppoatm_pop()
157 if (test_and_clear_bit(BLOCKED, &pvcc->blocked)) in pppoatm_pop()
158 tasklet_schedule(&pvcc->wakeup_tasklet); in pppoatm_pop()
162 * Unbind from PPP - currently we only do this when closing the socket,
169 atmvcc->push = pvcc->old_push; in pppoatm_unassign_vcc()
170 atmvcc->pop = pvcc->old_pop; in pppoatm_unassign_vcc()
171 atmvcc->release_cb = pvcc->old_release_cb; in pppoatm_unassign_vcc()
172 tasklet_kill(&pvcc->wakeup_tasklet); in pppoatm_unassign_vcc()
173 ppp_unregister_channel(&pvcc->chan); in pppoatm_unassign_vcc()
174 atmvcc->user_back = NULL; in pppoatm_unassign_vcc()
183 if (skb == NULL) { /* VCC was closed */ in pppoatm_push()
186 pr_debug("removing ATMPPP VCC %p\n", pvcc); in pppoatm_push()
187 module = pvcc->old_owner; in pppoatm_push()
189 atmvcc->push(atmvcc, NULL); /* Pass along bad news */ in pppoatm_push()
193 atm_return(atmvcc, skb->truesize); in pppoatm_push()
194 switch (pvcc->encaps) { in pppoatm_push()
196 if (skb->len < LLC_LEN || in pppoatm_push()
197 memcmp(skb->data, pppllc, LLC_LEN)) in pppoatm_push()
202 if (pvcc->chan.ppp == NULL) { /* Not bound yet! */ in pppoatm_push()
206 if (skb->len >= sizeof(pppllc) && in pppoatm_push()
207 !memcmp(skb->data, pppllc, sizeof(pppllc))) { in pppoatm_push()
208 pvcc->encaps = e_llc; in pppoatm_push()
212 if (skb->len >= (sizeof(pppllc) - LLC_LEN) && in pppoatm_push()
213 !memcmp(skb->data, &pppllc[LLC_LEN], in pppoatm_push()
214 sizeof(pppllc) - LLC_LEN)) { in pppoatm_push()
215 pvcc->encaps = e_vc; in pppoatm_push()
216 pvcc->chan.mtu += LLC_LEN; in pppoatm_push()
219 pr_debug("Couldn't autodetect yet (skb: %6ph)\n", skb->data); in pppoatm_push()
224 ppp_input(&pvcc->chan, skb); in pppoatm_push()
229 ppp_input_error(&pvcc->chan, 0); in pppoatm_push()
236 * to check we don't exceed sk->sk_sndbuf. If userspace sets a in pppoatm_may_send()
241 if (atm_may_send(pvcc->atmvcc, size) && in pppoatm_may_send()
242 atomic_inc_not_zero(&pvcc->inflight)) in pppoatm_may_send()
248 * *must* be set before we do the atomic_inc() on pvcc->inflight. in pppoatm_may_send()
252 test_and_set_bit(BLOCKED, &pvcc->blocked); in pppoatm_may_send()
267 * taking the PPP channel's ->downl lock, which is held by the in pppoatm_may_send()
271 if (atm_may_send(pvcc->atmvcc, size) && in pppoatm_may_send()
272 atomic_inc_not_zero(&pvcc->inflight)) in pppoatm_may_send()
278 * Called by the ppp_generic.c to send a packet - returns true if packet
290 struct atm_vcc *vcc; in pppoatm_send() local
293 ATM_SKB(skb)->vcc = pvcc->atmvcc; in pppoatm_send()
294 pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); in pppoatm_send()
295 if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT)) in pppoatm_send()
298 vcc = ATM_SKB(skb)->vcc; in pppoatm_send()
299 bh_lock_sock(sk_atm(vcc)); in pppoatm_send()
300 if (sock_owned_by_user(sk_atm(vcc))) { in pppoatm_send()
303 * the socket. It needs to be seen by the time our ->release_cb gets in pppoatm_send()
306 test_and_set_bit(BLOCKED, &pvcc->blocked); in pppoatm_send()
309 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || in pppoatm_send()
310 test_bit(ATM_VF_CLOSE, &vcc->flags) || in pppoatm_send()
311 !test_bit(ATM_VF_READY, &vcc->flags)) { in pppoatm_send()
312 bh_unlock_sock(sk_atm(vcc)); in pppoatm_send()
317 switch (pvcc->encaps) { /* LLC encapsulation needed */ in pppoatm_send()
323 !pppoatm_may_send(pvcc, n->truesize)) { in pppoatm_send()
330 bh_unlock_sock(sk_atm(vcc)); in pppoatm_send()
333 } else if (!pppoatm_may_send(pvcc, skb->truesize)) in pppoatm_send()
338 if (!pppoatm_may_send(pvcc, skb->truesize)) in pppoatm_send()
342 bh_unlock_sock(sk_atm(vcc)); in pppoatm_send()
348 atm_account_tx(vcc, skb); in pppoatm_send()
349 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", in pppoatm_send()
350 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); in pppoatm_send()
351 ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) in pppoatm_send()
353 bh_unlock_sock(sk_atm(vcc)); in pppoatm_send()
356 bh_unlock_sock(sk_atm(vcc)); in pppoatm_send()
361 if ((pvcc->flags & SC_COMP_PROT) && skb_headroom(skb) > 0 && in pppoatm_send()
362 skb->data[-1] == '\0') in pppoatm_send()
373 return put_user(chan_to_pvcc(chan)->flags, (int __user *) arg) in pppoatm_devppp_ioctl()
374 ? -EFAULT : 0; in pppoatm_devppp_ioctl()
376 return get_user(chan_to_pvcc(chan)->flags, (int __user *) arg) in pppoatm_devppp_ioctl()
377 ? -EFAULT : 0; in pppoatm_devppp_ioctl()
379 return -ENOTTY; in pppoatm_devppp_ioctl()
393 * Each PPPoATM instance has its own tasklet - this is just a in pppoatm_assign_vcc()
398 return -EFAULT; in pppoatm_assign_vcc()
401 return -EINVAL; in pppoatm_assign_vcc()
404 return -ENOMEM; in pppoatm_assign_vcc()
405 pvcc->atmvcc = atmvcc; in pppoatm_assign_vcc()
408 atomic_set(&pvcc->inflight, NONE_INFLIGHT); in pppoatm_assign_vcc()
409 pvcc->old_push = atmvcc->push; in pppoatm_assign_vcc()
410 pvcc->old_pop = atmvcc->pop; in pppoatm_assign_vcc()
411 pvcc->old_owner = atmvcc->owner; in pppoatm_assign_vcc()
412 pvcc->old_release_cb = atmvcc->release_cb; in pppoatm_assign_vcc()
413 pvcc->encaps = (enum pppoatm_encaps) be.encaps; in pppoatm_assign_vcc()
414 pvcc->chan.private = pvcc; in pppoatm_assign_vcc()
415 pvcc->chan.ops = &pppoatm_ops; in pppoatm_assign_vcc()
416 pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN - in pppoatm_assign_vcc()
418 pvcc->wakeup_tasklet = tasklet_proto; in pppoatm_assign_vcc()
419 pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan; in pppoatm_assign_vcc()
420 err = ppp_register_channel(&pvcc->chan); in pppoatm_assign_vcc()
425 atmvcc->user_back = pvcc; in pppoatm_assign_vcc()
426 atmvcc->push = pppoatm_push; in pppoatm_assign_vcc()
427 atmvcc->pop = pppoatm_pop; in pppoatm_assign_vcc()
428 atmvcc->release_cb = pppoatm_release_cb; in pppoatm_assign_vcc()
430 atmvcc->owner = THIS_MODULE; in pppoatm_assign_vcc()
432 /* re-process everything received between connection setup and in pppoatm_assign_vcc()
439 * This handles ioctls actually performed on our vcc - we must return
440 * -ENOIOCTLCMD for any unrecognized ioctl
448 if (cmd != ATM_SETBACKEND && atmvcc->push != pppoatm_push) in pppoatm_ioctl()
449 return -ENOIOCTLCMD; in pppoatm_ioctl()
454 return -EFAULT; in pppoatm_ioctl()
456 return -ENOIOCTLCMD; in pppoatm_ioctl()
458 return -EPERM; in pppoatm_ioctl()
459 if (sock->state != SS_CONNECTED) in pppoatm_ioctl()
460 return -EINVAL; in pppoatm_ioctl()
464 return put_user(ppp_channel_index(&atmvcc_to_pvcc(atmvcc)-> in pppoatm_ioctl()
465 chan), (int __user *) argp) ? -EFAULT : 0; in pppoatm_ioctl()
467 return put_user(ppp_unit_number(&atmvcc_to_pvcc(atmvcc)-> in pppoatm_ioctl()
468 chan), (int __user *) argp) ? -EFAULT : 0; in pppoatm_ioctl()
470 return -ENOIOCTLCMD; in pppoatm_ioctl()