Lines Matching +full:no +full:- +full:ether +full:- +full:link
1 // SPDX-License-Identifier: GPL-2.0-only
6 * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
13 (exist,new) -> 0,0 when "PVC create" or if "link unreliable"
14 0,x -> 1,1 if "link reliable" when sending FULL STATUS
15 1,1 -> 1,0 if received FULL STATUS ACK
17 (active) -> 0 when "ifconfig PVC down" or "link unreliable" or "PVC create"
18 -> 1 when "PVC up" and (exist,new) = 1,0
21 (exist,new,active) = FULL STATUS if "link reliable"
22 = 0, 0, 0 if "link unreliable"
23 No LMI:
24 active = open and "link reliable"
27 CCITT LMI: ITU-T Q.933 Annex A
77 #define LMI_INTEGRITY 0x01 /* link integrity report */
84 #define LMI_INTEG_LEN 2 /* link integrity element length */
118 struct net_device *ether; /* bridged Ethernet interface */ member
171 return(struct frad_state *)(hdlc->state); in state()
177 struct pvc_device *pvc = state(hdlc)->first_pvc; in find_pvc()
180 if (pvc->dlci == dlci) in find_pvc()
182 if (pvc->dlci > dlci) in find_pvc()
184 pvc = pvc->next; in find_pvc()
194 struct pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc; in add_pvc()
197 if ((*pvc_p)->dlci == dlci) in add_pvc()
199 if ((*pvc_p)->dlci > dlci) in add_pvc()
201 pvc_p = &(*pvc_p)->next; in add_pvc()
211 pvc->dlci = dlci; in add_pvc()
212 pvc->frad = dev; in add_pvc()
213 pvc->next = *pvc_p; /* Put it in the chain */ in add_pvc()
221 return pvc->main || pvc->ether; in pvc_is_used()
228 if (pvc->main) in pvc_carrier()
229 if (!netif_carrier_ok(pvc->main)) in pvc_carrier()
230 netif_carrier_on(pvc->main); in pvc_carrier()
231 if (pvc->ether) in pvc_carrier()
232 if (!netif_carrier_ok(pvc->ether)) in pvc_carrier()
233 netif_carrier_on(pvc->ether); in pvc_carrier()
235 if (pvc->main) in pvc_carrier()
236 if (netif_carrier_ok(pvc->main)) in pvc_carrier()
237 netif_carrier_off(pvc->main); in pvc_carrier()
238 if (pvc->ether) in pvc_carrier()
239 if (netif_carrier_ok(pvc->ether)) in pvc_carrier()
240 netif_carrier_off(pvc->ether); in pvc_carrier()
247 struct pvc_device **pvc_p = &state(hdlc)->first_pvc; in delete_unused_pvcs()
255 *pvc_p = pvc->next; in delete_unused_pvcs()
259 pvc_p = &(*pvc_p)->next; in delete_unused_pvcs()
268 return &pvc->ether; in get_dev_p()
270 return &pvc->main; in get_dev_p()
276 if (!skb->dev) { /* Control packets */ in fr_hard_header()
280 skb->data[3] = NLPID_CCITT_ANSI_LMI; in fr_hard_header()
285 skb->data[3] = NLPID_CISCO_LMI; in fr_hard_header()
289 return -EINVAL; in fr_hard_header()
292 } else if (skb->dev->type == ARPHRD_DLCI) { in fr_hard_header()
293 switch (skb->protocol) { in fr_hard_header()
296 skb->data[3] = NLPID_IP; in fr_hard_header()
301 skb->data[3] = NLPID_IPV6; in fr_hard_header()
306 skb->data[3] = FR_PAD; in fr_hard_header()
307 skb->data[4] = NLPID_SNAP; in fr_hard_header()
308 /* OUI 00-00-00 indicates an Ethertype follows */ in fr_hard_header()
309 skb->data[5] = 0x00; in fr_hard_header()
310 skb->data[6] = 0x00; in fr_hard_header()
311 skb->data[7] = 0x00; in fr_hard_header()
313 *(__be16 *)(skb->data + 8) = skb->protocol; in fr_hard_header()
316 } else if (skb->dev->type == ARPHRD_ETHER) { in fr_hard_header()
318 skb->data[3] = FR_PAD; in fr_hard_header()
319 skb->data[4] = NLPID_SNAP; in fr_hard_header()
320 /* OUI 00-80-C2 stands for the 802.1 organization */ in fr_hard_header()
321 skb->data[5] = 0x00; in fr_hard_header()
322 skb->data[6] = 0x80; in fr_hard_header()
323 skb->data[7] = 0xC2; in fr_hard_header()
324 /* PID 00-07 stands for Ethernet frames without FCS */ in fr_hard_header()
325 skb->data[8] = 0x00; in fr_hard_header()
326 skb->data[9] = 0x07; in fr_hard_header()
329 return -EINVAL; in fr_hard_header()
332 dlci_to_q922(skb->data, dlci); in fr_hard_header()
333 skb->data[2] = FR_UI; in fr_hard_header()
341 struct pvc_device *pvc = dev->ml_priv; in pvc_open()
343 if ((pvc->frad->flags & IFF_UP) == 0) in pvc_open()
344 return -EIO; /* Frad must be UP in order to activate PVC */ in pvc_open()
346 if (pvc->open_count++ == 0) { in pvc_open()
347 hdlc_device *hdlc = dev_to_hdlc(pvc->frad); in pvc_open()
348 if (state(hdlc)->settings.lmi == LMI_NONE) in pvc_open()
349 pvc->state.active = netif_carrier_ok(pvc->frad); in pvc_open()
351 pvc_carrier(pvc->state.active, pvc); in pvc_open()
352 state(hdlc)->dce_changed = 1; in pvc_open()
361 struct pvc_device *pvc = dev->ml_priv; in pvc_close()
363 if (--pvc->open_count == 0) { in pvc_close()
364 hdlc_device *hdlc = dev_to_hdlc(pvc->frad); in pvc_close()
365 if (state(hdlc)->settings.lmi == LMI_NONE) in pvc_close()
366 pvc->state.active = 0; in pvc_close()
368 if (state(hdlc)->settings.dce) { in pvc_close()
369 state(hdlc)->dce_changed = 1; in pvc_close()
370 pvc->state.active = 0; in pvc_close()
380 struct pvc_device *pvc = dev->ml_priv; in pvc_ioctl()
383 if (ifr->ifr_settings.type == IF_GET_PROTO) { in pvc_ioctl()
384 if (dev->type == ARPHRD_ETHER) in pvc_ioctl()
385 ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC; in pvc_ioctl()
387 ifr->ifr_settings.type = IF_PROTO_FR_PVC; in pvc_ioctl()
389 if (ifr->ifr_settings.size < sizeof(info)) { in pvc_ioctl()
391 ifr->ifr_settings.size = sizeof(info); in pvc_ioctl()
392 return -ENOBUFS; in pvc_ioctl()
395 info.dlci = pvc->dlci; in pvc_ioctl()
396 memcpy(info.master, pvc->frad->name, IFNAMSIZ); in pvc_ioctl()
397 if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, in pvc_ioctl()
399 return -EFAULT; in pvc_ioctl()
403 return -EINVAL; in pvc_ioctl()
408 struct pvc_device *pvc = dev->ml_priv; in pvc_xmit()
410 if (!pvc->state.active) in pvc_xmit()
413 if (dev->type == ARPHRD_ETHER) { in pvc_xmit()
414 int pad = ETH_ZLEN - skb->len; in pvc_xmit()
423 /* We already requested the header space with dev->needed_headroom. in pvc_xmit()
425 * dev->needed_headroom into consideration. in pvc_xmit()
436 skb->dev = dev; in pvc_xmit()
437 if (fr_hard_header(skb, pvc->dlci)) in pvc_xmit()
440 dev->stats.tx_bytes += skb->len; in pvc_xmit()
441 dev->stats.tx_packets++; in pvc_xmit()
442 if (pvc->state.fecn) /* TX Congestion counter */ in pvc_xmit()
443 dev->stats.tx_compressed++; in pvc_xmit()
444 skb->dev = pvc->frad; in pvc_xmit()
445 skb->protocol = htons(ETH_P_HDLC); in pvc_xmit()
451 dev->stats.tx_dropped++; in pvc_xmit()
458 netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n", in fr_log_dlci_active()
459 pvc->dlci, in fr_log_dlci_active()
460 pvc->main ? pvc->main->name : "", in fr_log_dlci_active()
461 pvc->main && pvc->ether ? " " : "", in fr_log_dlci_active()
462 pvc->ether ? pvc->ether->name : "", in fr_log_dlci_active()
463 pvc->state.new ? " new" : "", in fr_log_dlci_active()
464 !pvc->state.exist ? "deleted" : in fr_log_dlci_active()
465 pvc->state.active ? "active" : "inactive"); in fr_log_dlci_active()
481 struct pvc_device *pvc = state(hdlc)->first_pvc; in fr_lmi_send()
482 int lmi = state(hdlc)->settings.lmi; in fr_lmi_send()
483 int dce = state(hdlc)->settings.dce; in fr_lmi_send()
490 len += state(hdlc)->dce_pvc_count * (2 + stat_len); in fr_lmi_send()
502 memset(skb->data, 0, len); in fr_lmi_send()
520 data[i++] = state(hdlc)->txseq = in fr_lmi_send()
521 fr_lmi_nextseq(state(hdlc)->txseq); in fr_lmi_send()
522 data[i++] = state(hdlc)->rxseq; in fr_lmi_send()
531 if (state(hdlc)->reliable && !pvc->state.exist) { in fr_lmi_send()
532 pvc->state.exist = pvc->state.new = 1; in fr_lmi_send()
537 if (pvc->open_count && !pvc->state.active && in fr_lmi_send()
538 pvc->state.exist && !pvc->state.new) { in fr_lmi_send()
540 pvc->state.active = 1; in fr_lmi_send()
545 data[i] = pvc->dlci >> 8; in fr_lmi_send()
546 data[i + 1] = pvc->dlci & 0xFF; in fr_lmi_send()
548 data[i] = (pvc->dlci >> 4) & 0x3F; in fr_lmi_send()
549 data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80; in fr_lmi_send()
553 if (pvc->state.new) in fr_lmi_send()
555 else if (pvc->state.active) in fr_lmi_send()
559 pvc = pvc->next; in fr_lmi_send()
564 skb->priority = TC_PRIO_CONTROL; in fr_lmi_send()
565 skb->dev = dev; in fr_lmi_send()
566 skb->protocol = htons(ETH_P_HDLC); in fr_lmi_send()
577 struct pvc_device *pvc = state(hdlc)->first_pvc; in fr_set_link_state()
579 state(hdlc)->reliable = reliable; in fr_set_link_state()
582 state(hdlc)->n391cnt = 0; /* Request full status */ in fr_set_link_state()
583 state(hdlc)->dce_changed = 1; in fr_set_link_state()
585 if (state(hdlc)->settings.lmi == LMI_NONE) { in fr_set_link_state()
588 pvc->state.exist = pvc->state.active = 1; in fr_set_link_state()
589 pvc->state.new = 0; in fr_set_link_state()
590 pvc = pvc->next; in fr_set_link_state()
597 pvc->state.exist = pvc->state.active = 0; in fr_set_link_state()
598 pvc->state.new = 0; in fr_set_link_state()
599 if (!state(hdlc)->settings.dce) in fr_set_link_state()
600 pvc->state.bandwidth = 0; in fr_set_link_state()
601 pvc = pvc->next; in fr_set_link_state()
610 struct net_device *dev = st->dev; in fr_timer()
615 if (state(hdlc)->settings.dce) { in fr_timer()
616 reliable = state(hdlc)->request && in fr_timer()
617 time_before(jiffies, state(hdlc)->last_poll + in fr_timer()
618 state(hdlc)->settings.t392 * HZ); in fr_timer()
619 state(hdlc)->request = 0; in fr_timer()
621 state(hdlc)->last_errors <<= 1; /* Shift the list */ in fr_timer()
622 if (state(hdlc)->request) { in fr_timer()
623 if (state(hdlc)->reliable) in fr_timer()
624 netdev_info(dev, "No LMI status reply received\n"); in fr_timer()
625 state(hdlc)->last_errors |= 1; in fr_timer()
628 list = state(hdlc)->last_errors; in fr_timer()
629 for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1) in fr_timer()
632 reliable = (cnt < state(hdlc)->settings.n392); in fr_timer()
635 if (state(hdlc)->reliable != reliable) { in fr_timer()
636 netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un"); in fr_timer()
640 if (state(hdlc)->settings.dce) in fr_timer()
641 state(hdlc)->timer.expires = jiffies + in fr_timer()
642 state(hdlc)->settings.t392 * HZ; in fr_timer()
644 if (state(hdlc)->n391cnt) in fr_timer()
645 state(hdlc)->n391cnt--; in fr_timer()
647 fr_lmi_send(dev, state(hdlc)->n391cnt == 0); in fr_timer()
649 state(hdlc)->last_poll = jiffies; in fr_timer()
650 state(hdlc)->request = 1; in fr_timer()
651 state(hdlc)->timer.expires = jiffies + in fr_timer()
652 state(hdlc)->settings.t391 * HZ; in fr_timer()
655 add_timer(&state(hdlc)->timer); in fr_timer()
664 int lmi = state(hdlc)->settings.lmi; in fr_lmi_recv()
665 int dce = state(hdlc)->settings.dce; in fr_lmi_recv()
668 if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : in fr_lmi_recv()
674 if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : in fr_lmi_recv()
676 netdev_info(dev, "Received non-LMI frame with LMI DLCI\n"); in fr_lmi_recv()
680 if (skb->data[4] != LMI_CALLREF) { in fr_lmi_recv()
682 skb->data[4]); in fr_lmi_recv()
686 if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { in fr_lmi_recv()
688 skb->data[5]); in fr_lmi_recv()
693 if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { in fr_lmi_recv()
695 skb->data[6]); in fr_lmi_recv()
702 if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : in fr_lmi_recv()
705 skb->data[i]); in fr_lmi_recv()
709 if (skb->data[++i] != LMI_REPT_LEN) { in fr_lmi_recv()
711 skb->data[i]); in fr_lmi_recv()
715 reptype = skb->data[++i]; in fr_lmi_recv()
722 if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : in fr_lmi_recv()
724 netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n", in fr_lmi_recv()
725 skb->data[i]); in fr_lmi_recv()
729 if (skb->data[++i] != LMI_INTEG_LEN) { in fr_lmi_recv()
730 netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n", in fr_lmi_recv()
731 skb->data[i]); in fr_lmi_recv()
736 state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */ in fr_lmi_recv()
737 rxseq = skb->data[i++]; /* Should confirm our sequence */ in fr_lmi_recv()
739 txseq = state(hdlc)->txseq; in fr_lmi_recv()
742 state(hdlc)->last_poll = jiffies; in fr_lmi_recv()
745 if (!state(hdlc)->reliable) in fr_lmi_recv()
749 state(hdlc)->n391cnt = 0; in fr_lmi_recv()
754 if (state(hdlc)->fullrep_sent && !error) { in fr_lmi_recv()
755 /* Stop sending full report - the last one has been confirmed by DTE */ in fr_lmi_recv()
756 state(hdlc)->fullrep_sent = 0; in fr_lmi_recv()
757 pvc = state(hdlc)->first_pvc; in fr_lmi_recv()
759 if (pvc->state.new) { in fr_lmi_recv()
760 pvc->state.new = 0; in fr_lmi_recv()
763 state(hdlc)->dce_changed = 1; in fr_lmi_recv()
765 pvc = pvc->next; in fr_lmi_recv()
769 if (state(hdlc)->dce_changed) { in fr_lmi_recv()
771 state(hdlc)->fullrep_sent = 1; in fr_lmi_recv()
772 state(hdlc)->dce_changed = 0; in fr_lmi_recv()
775 state(hdlc)->request = 1; /* got request */ in fr_lmi_recv()
782 state(hdlc)->request = 0; /* got response, no request pending */ in fr_lmi_recv()
790 pvc = state(hdlc)->first_pvc; in fr_lmi_recv()
793 pvc->state.deleted = 1; in fr_lmi_recv()
794 pvc = pvc->next; in fr_lmi_recv()
798 while (skb->len >= i + 2 + stat_len) { in fr_lmi_recv()
803 if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : in fr_lmi_recv()
806 skb->data[i]); in fr_lmi_recv()
810 if (skb->data[++i] != stat_len) { in fr_lmi_recv()
812 skb->data[i]); in fr_lmi_recv()
817 new = !! (skb->data[i + 2] & 0x08); in fr_lmi_recv()
818 active = !! (skb->data[i + 2] & 0x02); in fr_lmi_recv()
820 dlci = (skb->data[i] << 8) | skb->data[i + 1]; in fr_lmi_recv()
821 bw = (skb->data[i + 3] << 16) | in fr_lmi_recv()
822 (skb->data[i + 4] << 8) | in fr_lmi_recv()
823 (skb->data[i + 5]); in fr_lmi_recv()
825 dlci = ((skb->data[i] & 0x3F) << 4) | in fr_lmi_recv()
826 ((skb->data[i + 1] & 0x78) >> 3); in fr_lmi_recv()
838 pvc->state.exist = 1; in fr_lmi_recv()
839 pvc->state.deleted = 0; in fr_lmi_recv()
840 if (active != pvc->state.active || in fr_lmi_recv()
841 new != pvc->state.new || in fr_lmi_recv()
842 bw != pvc->state.bandwidth || in fr_lmi_recv()
843 !pvc->state.exist) { in fr_lmi_recv()
844 pvc->state.new = new; in fr_lmi_recv()
845 pvc->state.active = active; in fr_lmi_recv()
846 pvc->state.bandwidth = bw; in fr_lmi_recv()
855 pvc = state(hdlc)->first_pvc; in fr_lmi_recv()
858 if (pvc->state.deleted && pvc->state.exist) { in fr_lmi_recv()
860 pvc->state.active = pvc->state.new = 0; in fr_lmi_recv()
861 pvc->state.exist = 0; in fr_lmi_recv()
862 pvc->state.bandwidth = 0; in fr_lmi_recv()
865 pvc = pvc->next; in fr_lmi_recv()
869 state(hdlc)->n391cnt = state(hdlc)->settings.n391; in fr_lmi_recv()
877 struct net_device *frad = skb->dev; in fr_rx()
879 struct fr_hdr *fh = (struct fr_hdr *)skb->data; in fr_rx()
880 u8 *data = skb->data; in fr_rx()
885 if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI) in fr_rx()
888 dlci = q922_to_dlci(skb->data); in fr_rx()
891 (state(hdlc)->settings.lmi == LMI_ANSI || in fr_rx()
892 state(hdlc)->settings.lmi == LMI_CCITT)) || in fr_rx()
894 state(hdlc)->settings.lmi == LMI_CISCO)) { in fr_rx()
904 netdev_info(frad, "No PVC for received frame's DLCI %d\n", in fr_rx()
911 if (pvc->state.fecn != fh->fecn) { in fr_rx()
913 printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name, in fr_rx()
914 dlci, fh->fecn ? "N" : "FF"); in fr_rx()
916 pvc->state.fecn ^= 1; in fr_rx()
919 if (pvc->state.becn != fh->becn) { in fr_rx()
921 printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name, in fr_rx()
922 dlci, fh->becn ? "N" : "FF"); in fr_rx()
924 pvc->state.becn ^= 1; in fr_rx()
929 frad->stats.rx_dropped++; in fr_rx()
934 skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ in fr_rx()
935 dev = pvc->main; in fr_rx()
936 skb->protocol = htons(ETH_P_IP); in fr_rx()
939 skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ in fr_rx()
940 dev = pvc->main; in fr_rx()
941 skb->protocol = htons(ETH_P_IPV6); in fr_rx()
943 } else if (skb->len > 10 && data[3] == FR_PAD && in fr_rx()
954 dev = pvc->main; in fr_rx()
955 skb->protocol = htons(pid); in fr_rx()
959 if ((dev = pvc->ether) != NULL) in fr_rx()
960 skb->protocol = eth_type_trans(skb, dev); in fr_rx()
971 data[3], skb->len); in fr_rx()
977 dev->stats.rx_packets++; /* PVC traffic */ in fr_rx()
978 dev->stats.rx_bytes += skb->len; in fr_rx()
979 if (pvc->state.becn) in fr_rx()
980 dev->stats.rx_compressed++; in fr_rx()
981 skb->dev = dev; in fr_rx()
990 frad->stats.rx_errors++; /* Mark error */ in fr_rx()
1003 if (state(hdlc)->settings.lmi != LMI_NONE) { in fr_start()
1004 state(hdlc)->reliable = 0; in fr_start()
1005 state(hdlc)->dce_changed = 1; in fr_start()
1006 state(hdlc)->request = 0; in fr_start()
1007 state(hdlc)->fullrep_sent = 0; in fr_start()
1008 state(hdlc)->last_errors = 0xFFFFFFFF; in fr_start()
1009 state(hdlc)->n391cnt = 0; in fr_start()
1010 state(hdlc)->txseq = state(hdlc)->rxseq = 0; in fr_start()
1012 state(hdlc)->dev = dev; in fr_start()
1013 timer_setup(&state(hdlc)->timer, fr_timer, 0); in fr_start()
1015 state(hdlc)->timer.expires = jiffies + HZ; in fr_start()
1016 add_timer(&state(hdlc)->timer); in fr_start()
1028 if (state(hdlc)->settings.lmi != LMI_NONE) in fr_stop()
1029 del_timer_sync(&state(hdlc)->timer); in fr_stop()
1037 struct pvc_device *pvc = state(hdlc)->first_pvc; in fr_close()
1040 if (pvc->main) in fr_close()
1041 dev_close(pvc->main); in fr_close()
1042 if (pvc->ether) in fr_close()
1043 dev_close(pvc->ether); in fr_close()
1044 pvc = pvc->next; in fr_close()
1051 dev->type = ARPHRD_DLCI; in pvc_setup()
1052 dev->flags = IFF_POINTOPOINT; in pvc_setup()
1053 dev->hard_header_len = 0; in pvc_setup()
1054 dev->addr_len = 2; in pvc_setup()
1074 return -ENOBUFS; in fr_add_pvc()
1078 return -EEXIST; in fr_add_pvc()
1091 return -ENOBUFS; in fr_add_pvc()
1095 dev->priv_flags &= ~IFF_TX_SKB_SHARING; in fr_add_pvc()
1098 *(__be16*)dev->dev_addr = htons(dlci); in fr_add_pvc()
1099 dlci_to_q922(dev->broadcast, dlci); in fr_add_pvc()
1101 dev->netdev_ops = &pvc_ops; in fr_add_pvc()
1102 dev->mtu = HDLC_MAX_MTU; in fr_add_pvc()
1103 dev->min_mtu = 68; in fr_add_pvc()
1104 dev->max_mtu = HDLC_MAX_MTU; in fr_add_pvc()
1105 dev->needed_headroom = 10; in fr_add_pvc()
1106 dev->priv_flags |= IFF_NO_QUEUE; in fr_add_pvc()
1107 dev->ml_priv = pvc; in fr_add_pvc()
1112 return -EIO; in fr_add_pvc()
1115 dev->needs_free_netdev = true; in fr_add_pvc()
1118 state(hdlc)->dce_changed = 1; in fr_add_pvc()
1119 state(hdlc)->dce_pvc_count++; in fr_add_pvc()
1132 return -ENOENT; in fr_del_pvc()
1135 return -ENOENT; in fr_del_pvc()
1137 if (dev->flags & IFF_UP) in fr_del_pvc()
1138 return -EBUSY; /* PVC in use */ in fr_del_pvc()
1144 state(hdlc)->dce_pvc_count--; in fr_del_pvc()
1145 state(hdlc)->dce_changed = 1; in fr_del_pvc()
1156 struct pvc_device *pvc = state(hdlc)->first_pvc; in fr_destroy()
1157 state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */ in fr_destroy()
1158 state(hdlc)->dce_pvc_count = 0; in fr_destroy()
1159 state(hdlc)->dce_changed = 1; in fr_destroy()
1162 struct pvc_device *next = pvc->next; in fr_destroy()
1163 /* destructors will free_netdev() main and ether */ in fr_destroy()
1164 if (pvc->main) in fr_destroy()
1165 unregister_netdevice(pvc->main); in fr_destroy()
1167 if (pvc->ether) in fr_destroy()
1168 unregister_netdevice(pvc->ether); in fr_destroy()
1189 fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; in fr_ioctl()
1196 switch (ifr->ifr_settings.type) { in fr_ioctl()
1198 if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ in fr_ioctl()
1199 return -EINVAL; in fr_ioctl()
1200 ifr->ifr_settings.type = IF_PROTO_FR; in fr_ioctl()
1201 if (ifr->ifr_settings.size < size) { in fr_ioctl()
1202 ifr->ifr_settings.size = size; /* data size wanted */ in fr_ioctl()
1203 return -ENOBUFS; in fr_ioctl()
1205 if (copy_to_user(fr_s, &state(hdlc)->settings, size)) in fr_ioctl()
1206 return -EFAULT; in fr_ioctl()
1211 return -EPERM; in fr_ioctl()
1213 if (dev->flags & IFF_UP) in fr_ioctl()
1214 return -EBUSY; in fr_ioctl()
1217 return -EFAULT; in fr_ioctl()
1234 return -EINVAL; in fr_ioctl()
1236 result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); in fr_ioctl()
1240 if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ in fr_ioctl()
1245 state(hdlc)->first_pvc = NULL; in fr_ioctl()
1246 state(hdlc)->dce_pvc_count = 0; in fr_ioctl()
1248 memcpy(&state(hdlc)->settings, &new_settings, size); in fr_ioctl()
1249 dev->type = ARPHRD_FRAD; in fr_ioctl()
1257 if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ in fr_ioctl()
1258 return -EINVAL; in fr_ioctl()
1261 return -EPERM; in fr_ioctl()
1263 if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, in fr_ioctl()
1265 return -EFAULT; in fr_ioctl()
1268 return -EINVAL; /* Only 10 bits, DLCI 0 reserved */ in fr_ioctl()
1270 if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC || in fr_ioctl()
1271 ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC) in fr_ioctl()
1276 if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || in fr_ioctl()
1277 ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) in fr_ioctl()
1283 return -EINVAL; in fr_ioctl()
1304 MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC");