Skip to content

Commit

Permalink
[PATCH] Modularize generic HDLC
Browse files Browse the repository at this point in the history
This patch enables building of individual WAN protocol support
routines (parts of generic HDLC) as separate modules.
All protocol-private definitions are moved from hdlc.h file
to protocol drivers. User-space interface and interface
between generic HDLC and underlying low-level HDLC drivers
are unchanged.

Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Krzysztof Halasa authored and Jeff Garzik committed Sep 26, 2006
1 parent c226951 commit eb2a2fd
Show file tree
Hide file tree
Showing 11 changed files with 743 additions and 508 deletions.
12 changes: 6 additions & 6 deletions drivers/net/wan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ config HDLC
If unsure, say N.

config HDLC_RAW
bool "Raw HDLC support"
tristate "Raw HDLC support"
depends on HDLC
help
Generic HDLC driver supporting raw HDLC over WAN connections.

If unsure, say N.

config HDLC_RAW_ETH
bool "Raw HDLC Ethernet device support"
tristate "Raw HDLC Ethernet device support"
depends on HDLC
help
Generic HDLC driver supporting raw HDLC Ethernet device emulation
Expand All @@ -173,31 +173,31 @@ config HDLC_RAW_ETH
If unsure, say N.

config HDLC_CISCO
bool "Cisco HDLC support"
tristate "Cisco HDLC support"
depends on HDLC
help
Generic HDLC driver supporting Cisco HDLC over WAN connections.

If unsure, say N.

config HDLC_FR
bool "Frame Relay support"
tristate "Frame Relay support"
depends on HDLC
help
Generic HDLC driver supporting Frame Relay over WAN connections.

If unsure, say N.

config HDLC_PPP
bool "Synchronous Point-to-Point Protocol (PPP) support"
tristate "Synchronous Point-to-Point Protocol (PPP) support"
depends on HDLC
help
Generic HDLC driver supporting PPP over WAN connections.

If unsure, say N.

config HDLC_X25
bool "X.25 protocol support"
tristate "X.25 protocol support"
depends on HDLC && (LAPB=m && HDLC=m || LAPB=y)
help
Generic HDLC driver supporting X.25 over WAN connections.
Expand Down
19 changes: 7 additions & 12 deletions drivers/net/wan/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ cyclomx-y := cycx_main.o
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
cyclomx-objs := $(cyclomx-y)

hdlc-y := hdlc_generic.o
hdlc-$(CONFIG_HDLC_RAW) += hdlc_raw.o
hdlc-$(CONFIG_HDLC_RAW_ETH) += hdlc_raw_eth.o
hdlc-$(CONFIG_HDLC_CISCO) += hdlc_cisco.o
hdlc-$(CONFIG_HDLC_FR) += hdlc_fr.o
hdlc-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
hdlc-$(CONFIG_HDLC_X25) += hdlc_x25.o
hdlc-objs := $(hdlc-y)
obj-$(CONFIG_HDLC) += hdlc.o
obj-$(CONFIG_HDLC_RAW) += hdlc_raw.o
obj-$(CONFIG_HDLC_RAW_ETH) += hdlc_raw_eth.o
obj-$(CONFIG_HDLC_CISCO) += hdlc_cisco.o
obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o syncppp.o
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o

pc300-y := pc300_drv.o
pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
Expand All @@ -38,10 +37,6 @@ obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o
obj-$(CONFIG_PC300) += pc300.o
obj-$(CONFIG_HDLC) += hdlc.o
ifeq ($(CONFIG_HDLC_PPP),y)
obj-$(CONFIG_HDLC) += syncppp.o
endif
obj-$(CONFIG_N2) += n2.o
obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o
Expand Down
169 changes: 99 additions & 70 deletions drivers/net/wan/hdlc_generic.c → drivers/net/wan/hdlc.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Generic HDLC support routines for Linux
*
* Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999 - 2006 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
Expand All @@ -17,9 +17,9 @@
* Use sethdlc utility to set line parameters, protocol and PVCs
*
* How does it work:
* - proto.open(), close(), start(), stop() calls are serialized.
* - 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.
* - proto->start() and stop() are called with spin_lock_irq held.
*/

#include <linux/module.h>
Expand All @@ -38,10 +38,12 @@
#include <linux/hdlc.h>


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

#undef DEBUG_LINK

static struct hdlc_proto *first_proto = NULL;


static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
{
Expand All @@ -63,11 +65,11 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *p, struct net_device *orig_dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.netif_rx)
return hdlc->proto.netif_rx(skb);
struct hdlc_device_desc *desc = dev_to_desc(dev);
if (desc->netif_rx)
return desc->netif_rx(skb);

hdlc->stats.rx_dropped++; /* Shouldn't happen */
desc->stats.rx_dropped++; /* Shouldn't happen */
dev_kfree_skb(skb);
return NET_RX_DROP;
}
Expand All @@ -77,17 +79,17 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
static inline void hdlc_proto_start(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.start)
return hdlc->proto.start(dev);
if (hdlc->proto->start)
return hdlc->proto->start(dev);
}



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


Expand Down Expand Up @@ -144,15 +146,15 @@ int hdlc_open(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
printk(KERN_DEBUG "%s: hdlc_open() carrier %i open %i\n", dev->name,
hdlc->carrier, hdlc->open);
#endif

if (hdlc->proto.id == -1)
if (hdlc->proto == NULL)
return -ENOSYS; /* no protocol attached */

if (hdlc->proto.open) {
int result = hdlc->proto.open(dev);
if (hdlc->proto->open) {
int result = hdlc->proto->open(dev);
if (result)
return result;
}
Expand All @@ -178,7 +180,7 @@ void hdlc_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
printk(KERN_DEBUG "%s: hdlc_close() carrier %i open %i\n", dev->name,
hdlc->carrier, hdlc->open);
#endif

Expand All @@ -190,68 +192,34 @@ void hdlc_close(struct net_device *dev)

spin_unlock_irq(&hdlc->state_lock);

if (hdlc->proto.close)
hdlc->proto.close(dev);
if (hdlc->proto->close)
hdlc->proto->close(dev);
}



#ifndef CONFIG_HDLC_RAW
#define hdlc_raw_ioctl(dev, ifr) -ENOSYS
#endif

#ifndef CONFIG_HDLC_RAW_ETH
#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS
#endif

#ifndef CONFIG_HDLC_PPP
#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS
#endif

#ifndef CONFIG_HDLC_CISCO
#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS
#endif

#ifndef CONFIG_HDLC_FR
#define hdlc_fr_ioctl(dev, ifr) -ENOSYS
#endif

#ifndef CONFIG_HDLC_X25
#define hdlc_x25_ioctl(dev, ifr) -ENOSYS
#endif


int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
unsigned int proto;
struct hdlc_proto *proto = first_proto;
int result;

if (cmd != SIOCWANDEV)
return -EINVAL;

switch(ifr->ifr_settings.type) {
case IF_PROTO_HDLC:
case IF_PROTO_HDLC_ETH:
case IF_PROTO_PPP:
case IF_PROTO_CISCO:
case IF_PROTO_FR:
case IF_PROTO_X25:
proto = ifr->ifr_settings.type;
break;

default:
proto = hdlc->proto.id;
if (dev_to_hdlc(dev)->proto) {
result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr);
if (result != -EINVAL)
return result;
}

switch(proto) {
case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr);
case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr);
case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr);
case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr);
case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr);
case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr);
default: return -EINVAL;
/* Not handled by currently attached protocol (if any) */

while (proto) {
if ((result = proto->ioctl(dev, ifr)) != -EINVAL)
return result;
proto = proto->next;
}
return -EINVAL;
}

void hdlc_setup(struct net_device *dev)
Expand All @@ -267,8 +235,6 @@ void hdlc_setup(struct net_device *dev)

dev->flags = IFF_POINTOPOINT | IFF_NOARP;

hdlc->proto.id = -1;
hdlc->proto.detach = NULL;
hdlc->carrier = 1;
hdlc->open = 0;
spin_lock_init(&hdlc->state_lock);
Expand All @@ -277,7 +243,8 @@ void hdlc_setup(struct net_device *dev)
struct net_device *alloc_hdlcdev(void *priv)
{
struct net_device *dev;
dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
dev = alloc_netdev(sizeof(struct hdlc_device_desc) +
sizeof(hdlc_device), "hdlc%d", hdlc_setup);
if (dev)
dev_to_hdlc(dev)->priv = priv;
return dev;
Expand All @@ -286,13 +253,71 @@ struct net_device *alloc_hdlcdev(void *priv)
void unregister_hdlc_device(struct net_device *dev)
{
rtnl_lock();
hdlc_proto_detach(dev_to_hdlc(dev));
unregister_netdevice(dev);
detach_hdlc_protocol(dev);
rtnl_unlock();
}



int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
int (*rx)(struct sk_buff *skb), size_t size)
{
detach_hdlc_protocol(dev);

if (!try_module_get(proto->module))
return -ENOSYS;

if (size)
if ((dev_to_hdlc(dev)->state = kmalloc(size,
GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "Memory squeeze on"
" hdlc_proto_attach()\n");
module_put(proto->module);
return -ENOBUFS;
}
dev_to_hdlc(dev)->proto = proto;
dev_to_desc(dev)->netif_rx = rx;
return 0;
}


void detach_hdlc_protocol(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);

if (hdlc->proto) {
if (hdlc->proto->detach)
hdlc->proto->detach(dev);
module_put(hdlc->proto->module);
hdlc->proto = NULL;
}
kfree(hdlc->state);
hdlc->state = NULL;
}


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


void unregister_hdlc_protocol(struct hdlc_proto *proto)
{
struct hdlc_proto **p = &first_proto;
while (*p) {
if (*p == proto) {
*p = proto->next;
return;
}
p = &((*p)->next);
}
}



MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("HDLC support module");
MODULE_LICENSE("GPL v2");
Expand All @@ -303,6 +328,10 @@ EXPORT_SYMBOL(hdlc_ioctl);
EXPORT_SYMBOL(hdlc_setup);
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 = {
.type = __constant_htons(ETH_P_HDLC),
Expand Down
Loading

0 comments on commit eb2a2fd

Please sign in to comment.