cregit-Linux how code gets into the kernel

Release 4.7 drivers/net/wan/hdlc.c

Directory: drivers/net/wan
/*
 * Generic HDLC support routines for Linux
 *
 * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 * Currently supported:
 *      * raw IP-in-HDLC
 *      * Cisco HDLC
 *      * Frame Relay with ANSI or CCITT LMI (both user and network side)
 *      * PPP
 *      * X.25
 *
 * Use sethdlc utility to set line parameters, protocol and PVCs
 *
 * How does it work:
 * - proto->open(), close(), start(), stop() calls are serialized.
 *   The order is: open, [ start, stop ... ] close ...
 * - proto->start() and stop() are called with spin_lock_irq held.
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/errno.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/pkt_sched.h>
#include <linux/poll.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <net/net_namespace.h>



static const char* version = "HDLC support module revision 1.22";


#undef DEBUG_LINK


static struct hdlc_proto *first_proto;


int hdlc_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) return -EINVAL; dev->mtu = new_mtu; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
francois romieufrancois romieu40100.00%1100.00%
Total40100.00%1100.00%


static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) { struct hdlc_device *hdlc = dev_to_hdlc(dev); if (!net_eq(dev_net(dev), &init_net)) { kfree_skb(skb); return 0; } BUG_ON(!hdlc->proto->netif_rx); return hdlc->proto->netif_rx(skb); }

Contributors

PersonTokensPropCommitsCommitProp
francois romieufrancois romieu2835.00%112.50%
krzysztof halasakrzysztof halasa2531.25%337.50%
eric w. biedermaneric w. biederman1417.50%112.50%
david s. millerdavid s. miller56.25%112.50%
octavian purdilaoctavian purdila56.25%112.50%
hideaki yoshifujihideaki yoshifuji33.75%112.50%
Total80100.00%8100.00%


netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->proto->xmit) return hdlc->proto->xmit(skb, dev); return hdlc->xmit(skb, dev); /* call hardware driver directly */ }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa5498.18%150.00%
stephen hemmingerstephen hemminger11.82%150.00%
Total55100.00%2100.00%


static inline void hdlc_proto_start(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->proto->start) hdlc->proto->start(dev); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa38100.00%4100.00%
Total38100.00%4100.00%


static inline void hdlc_proto_stop(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->proto->stop) hdlc->proto->stop(dev); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa38100.00%4100.00%
Total38100.00%4100.00%


static int hdlc_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); hdlc_device *hdlc; unsigned long flags; int on; if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; if (!(dev->priv_flags & IFF_WAN_HDLC)) return NOTIFY_DONE; /* not an HDLC device */ if (event != NETDEV_CHANGE) return NOTIFY_DONE; /* Only interested in carrier changes */ on = netif_carrier_ok(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "%s: hdlc_device_event NETDEV_CHANGE, carrier %i\n", dev->name, on); #endif hdlc = dev_to_hdlc(dev); spin_lock_irqsave(&hdlc->state_lock, flags); if (hdlc->carrier == on) goto carrier_exit; /* no change in DCD line level */ hdlc->carrier = on; if (!hdlc->open) goto carrier_exit; if (hdlc->carrier) { netdev_info(dev, "Carrier detected\n"); hdlc_proto_start(dev); } else { netdev_info(dev, "Carrier lost\n"); hdlc_proto_stop(dev); } carrier_exit: spin_unlock_irqrestore(&hdlc->state_lock, flags); return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa16481.59%541.67%
eric w. biedermaneric w. biederman104.98%18.33%
al viroal viro94.48%18.33%
joe perchesjoe perches62.99%18.33%
octavian purdilaoctavian purdila52.49%18.33%
jiri pirkojiri pirko31.49%18.33%
hideaki yoshifujihideaki yoshifuji31.49%18.33%
thomas weberthomas weber10.50%18.33%
Total201100.00%12100.00%

/* Must be called by hardware driver when HDLC device is being opened */
int hdlc_open(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "%s: hdlc_open() carrier %i open %i\n", dev->name, hdlc->carrier, hdlc->open); #endif if (hdlc->proto == NULL) return -ENOSYS; /* no protocol attached */ if (hdlc->proto->open) { int result = hdlc->proto->open(dev); if (result) return result; } spin_lock_irq(&hdlc->state_lock); if (hdlc->carrier) { netdev_info(dev, "Carrier detected\n"); hdlc_proto_start(dev); } else netdev_info(dev, "No carrier\n"); hdlc->open = 1; spin_unlock_irq(&hdlc->state_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa11785.40%457.14%
al viroal viro1410.22%228.57%
joe perchesjoe perches64.38%114.29%
Total137100.00%7100.00%

/* Must be called by hardware driver when HDLC device is being closed */
void hdlc_close(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "%s: hdlc_close() carrier %i open %i\n", dev->name, hdlc->carrier, hdlc->open); #endif spin_lock_irq(&hdlc->state_lock); hdlc->open = 0; if (hdlc->carrier) hdlc_proto_stop(dev); spin_unlock_irq(&hdlc->state_lock); if (hdlc->proto->close) hdlc->proto->close(dev); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa7884.78%360.00%
al viroal viro1415.22%240.00%
Total92100.00%5100.00%


int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct hdlc_proto *proto = first_proto; int result; if (cmd != SIOCWANDEV) return -EINVAL; if (dev_to_hdlc(dev)->proto) { result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr); if (result != -EINVAL) return result; } /* Not handled by currently attached protocol (if any) */ while (proto) { if ((result = proto->ioctl(dev, ifr)) != -EINVAL) return result; proto = proto->next; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa5750.44%342.86%
francois romieufrancois romieu5346.90%228.57%
al viroal viro32.65%228.57%
Total113100.00%7100.00%

static const struct header_ops hdlc_null_ops;
static void hdlc_setup_dev(struct net_device *dev) { /* Re-init all variables changed by HDLC protocol drivers, * including ether_setup() called from hdlc_raw_eth.c. */ dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->priv_flags = IFF_WAN_HDLC; dev->mtu = HDLC_MAX_MTU; dev->type = ARPHRD_RAWHDLC; dev->hard_header_len = 16; dev->addr_len = 0; dev->header_ops = &hdlc_null_ops; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro3357.89%120.00%
krzysztof halasakrzysztof halasa2035.09%240.00%
stephen hemmingerstephen hemminger35.26%120.00%
adrian bunkadrian bunk11.75%120.00%
Total57100.00%5100.00%


static void hdlc_setup(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_setup_dev(dev); hdlc->carrier = 1; hdlc->open = 0; spin_lock_init(&hdlc->state_lock); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa2351.11%150.00%
al viroal viro2248.89%150.00%
Total45100.00%2100.00%


struct net_device *alloc_hdlcdev(void *priv) { struct net_device *dev; dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", NET_NAME_UNKNOWN, hdlc_setup); if (dev) dev_to_hdlc(dev)->priv = priv; return dev; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro4693.88%250.00%
tom gundersentom gundersen24.08%125.00%
krzysztof halasakrzysztof halasa12.04%125.00%
Total49100.00%4100.00%


void unregister_hdlc_device(struct net_device *dev) { rtnl_lock(); detach_hdlc_protocol(dev); unregister_netdevice(dev); rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa1453.85%233.33%
francois romieufrancois romieu623.08%116.67%
al viroal viro311.54%116.67%
andrew lunnandrew lunn27.69%116.67%
david s. millerdavid s. miller13.85%116.67%
Total26100.00%6100.00%


int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, size_t size) { int err; err = detach_hdlc_protocol(dev); if (err) return err; if (!try_module_get(proto->module)) return -ENOSYS; if (size) { dev_to_hdlc(dev)->state = kmalloc(size, GFP_KERNEL); if (dev_to_hdlc(dev)->state == NULL) { module_put(proto->module); return -ENOBUFS; } } dev_to_hdlc(dev)->proto = proto; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa7369.52%120.00%
andrew lunnandrew lunn1211.43%120.00%
joe perchesjoe perches1110.48%120.00%
al viroal viro54.76%120.00%
francois romieufrancois romieu43.81%120.00%
Total105100.00%5100.00%


int detach_hdlc_protocol(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); int err; if (hdlc->proto) { err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); err = notifier_to_errno(err); if (err) { netdev_err(dev, "Refused to change device type\n"); return err; } if (hdlc->proto->detach) hdlc->proto->detach(dev); module_put(hdlc->proto->module); hdlc->proto = NULL; } kfree(hdlc->state); hdlc->state = NULL; hdlc_setup_dev(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa7464.35%250.00%
andrew lunnandrew lunn3933.91%125.00%
francois romieufrancois romieu21.74%125.00%
Total115100.00%4100.00%


void register_hdlc_protocol(struct hdlc_proto *proto) { rtnl_lock(); proto->next = first_proto; first_proto = proto; rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa26100.00%2100.00%
Total26100.00%2100.00%


void unregister_hdlc_protocol(struct hdlc_proto *proto) { struct hdlc_proto **p; rtnl_lock(); p = &first_proto; while (*p != proto) { BUG_ON(!*p); p = &((*p)->next); } *p = proto->next; rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa62100.00%2100.00%
Total62100.00%2100.00%

MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); MODULE_DESCRIPTION("HDLC support module"); MODULE_LICENSE("GPL v2"); EXPORT_SYMBOL(hdlc_change_mtu); EXPORT_SYMBOL(hdlc_start_xmit); EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_ioctl); EXPORT_SYMBOL(alloc_hdlcdev); EXPORT_SYMBOL(unregister_hdlc_device); EXPORT_SYMBOL(register_hdlc_protocol); EXPORT_SYMBOL(unregister_hdlc_protocol); EXPORT_SYMBOL(attach_hdlc_protocol); EXPORT_SYMBOL(detach_hdlc_protocol); static struct packet_type hdlc_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_HDLC), .func = hdlc_rcv, }; static struct notifier_block hdlc_notifier = { .notifier_call = hdlc_device_event, };
static int __init hdlc_module_init(void) { int result; pr_info("%s\n", version); if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0) return result; dev_add_pack(&hdlc_packet_type); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
francois romieufrancois romieu2453.33%133.33%
krzysztof halasakrzysztof halasa2044.44%133.33%
joe perchesjoe perches12.22%133.33%
Total45100.00%3100.00%


static void __exit hdlc_module_exit(void) { dev_remove_pack(&hdlc_packet_type); unregister_netdevice_notifier(&hdlc_notifier); }

Contributors

PersonTokensPropCommitsCommitProp
francois romieufrancois romieu1571.43%150.00%
krzysztof halasakrzysztof halasa628.57%150.00%
Total21100.00%2100.00%

module_init(hdlc_module_init); module_exit(hdlc_module_exit);

Overall Contributors

PersonTokensPropCommitsCommitProp
krzysztof halasakrzysztof halasa97763.73%1533.33%
francois romieufrancois romieu25416.57%24.44%
al viroal viro1499.72%920.00%
andrew lunnandrew lunn533.46%24.44%
joe perchesjoe perches312.02%24.44%
eric w. biedermaneric w. biederman271.76%24.44%
stephen hemmingerstephen hemminger110.72%36.67%
octavian purdilaoctavian purdila100.65%12.22%
david s. millerdavid s. miller60.39%24.44%
hideaki yoshifujihideaki yoshifuji60.39%12.22%
jiri pirkojiri pirko30.20%12.22%
tom gundersentom gundersen20.13%12.22%
adrian bunkadrian bunk10.07%12.22%
harvey harrisonharvey harrison10.07%12.22%
thomas weberthomas weber10.07%12.22%
andrew mortonandrew morton10.07%12.22%
Total1533100.00%45100.00%
Directory: drivers/net/wan
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}