cregit-Linux how code gets into the kernel

Release 4.11 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;


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
François Romieu2835.00%112.50%
Krzysztof Hałasa2531.25%337.50%
Eric W. Biedermann1417.50%112.50%
David S. Miller56.25%112.50%
Octavian Purdila56.25%112.50%
Hideaki Yoshifuji / 吉藤英明33.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 Hałasa5498.18%150.00%
Stephen 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 Hałasa38100.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 Hałasa38100.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 Hałasa16481.59%541.67%
Eric W. Biedermann104.98%18.33%
Al Viro94.48%18.33%
Joe Perches62.99%18.33%
Octavian Purdila52.49%18.33%
Jiri Pirko31.49%18.33%
Hideaki Yoshifuji / 吉藤英明31.49%18.33%
Thomas 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 Hałasa11785.40%457.14%
Al Viro1410.22%228.57%
Joe 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 Hałasa7884.78%360.00%
Al 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 Hałasa5750.44%342.86%
François Romieu5346.90%228.57%
Al 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->min_mtu = 68; dev->max_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 Viro3347.83%116.67%
Krzysztof Hałasa2028.99%233.33%
Jarod Wilson1217.39%116.67%
Stephen Hemminger34.35%116.67%
Adrian Bunk11.45%116.67%
Total69100.00%6100.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 Hałasa2351.11%150.00%
Al 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 Viro4693.88%250.00%
Tom Gundersen24.08%125.00%
Krzysztof Hałasa12.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 Hałasa1453.85%233.33%
François Romieu623.08%116.67%
Al Viro311.54%116.67%
Andrew Lunn27.69%116.67%
David 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 Hałasa7369.52%120.00%
Andrew Lunn1211.43%120.00%
Joe Perches1110.48%120.00%
Al Viro54.76%120.00%
François 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 Hałasa7464.35%250.00%
Andrew Lunn3933.91%125.00%
François 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 Hałasa26100.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 Hałasa62100.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_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
François Romieu2453.33%133.33%
Krzysztof Hałasa2044.44%133.33%
Joe 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
François Romieu1571.43%150.00%
Krzysztof Hałasa628.57%150.00%
Total21100.00%2100.00%

module_init(hdlc_module_init); module_exit(hdlc_module_exit);

Overall Contributors

PersonTokensPropCommitsCommitProp
Krzysztof Hałasa97264.80%1532.61%
François Romieu21414.27%24.35%
Al Viro1499.93%919.57%
Andrew Lunn533.53%24.35%
Joe Perches312.07%24.35%
Eric W. Biedermann271.80%24.35%
Jarod Wilson120.80%12.17%
Stephen Hemminger110.73%36.52%
Octavian Purdila100.67%12.17%
David S. Miller60.40%24.35%
Hideaki Yoshifuji / 吉藤英明60.40%12.17%
Jiri Pirko30.20%12.17%
Tom Gundersen20.13%12.17%
Adrian Bunk10.07%12.17%
Harvey Harrison10.07%12.17%
Andrew Morton10.07%12.17%
Thomas Weber10.07%12.17%
Total1500100.00%46100.00%
Directory: drivers/net/wan
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.