diff options
Diffstat (limited to 'drivers/net/wan')
-rw-r--r-- | drivers/net/wan/Kconfig | 95 | ||||
-rw-r--r-- | drivers/net/wan/Makefile | 19 | ||||
-rw-r--r-- | drivers/net/wan/cosa.c | 8 | ||||
-rw-r--r-- | drivers/net/wan/cycx_main.c | 8 | ||||
-rw-r--r-- | drivers/net/wan/dscc4.c | 4 | ||||
-rw-r--r-- | drivers/net/wan/farsync.c | 2 | ||||
-rw-r--r-- | drivers/net/wan/hd6457x.c | 2 | ||||
-rw-r--r-- | drivers/net/wan/hdlc.c (renamed from drivers/net/wan/hdlc_generic.c) | 169 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_cisco.c | 200 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_fr.c | 389 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_ppp.c | 77 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_raw.c | 50 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_raw_eth.c | 49 | ||||
-rw-r--r-- | drivers/net/wan/hdlc_x25.c | 54 | ||||
-rw-r--r-- | drivers/net/wan/lmc/lmc_main.c | 4 | ||||
-rw-r--r-- | drivers/net/wan/n2.c | 6 | ||||
-rw-r--r-- | drivers/net/wan/pc300.h | 1 | ||||
-rw-r--r-- | drivers/net/wan/pc300_drv.c | 58 | ||||
-rw-r--r-- | drivers/net/wan/pc300_tty.c | 23 | ||||
-rw-r--r-- | drivers/net/wan/sbni.c | 4 | ||||
-rw-r--r-- | drivers/net/wan/sdla.c | 10 | ||||
-rw-r--r-- | drivers/net/wan/syncppp.c | 4 | ||||
-rw-r--r-- | drivers/net/wan/wanxl.c | 2 | ||||
-rw-r--r-- | drivers/net/wan/z85230.c | 2 | ||||
-rw-r--r-- | drivers/net/wan/z85230.h | 2 |
25 files changed, 784 insertions, 458 deletions
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 54b8e492ef9..21f76f51c95 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -57,44 +57,6 @@ config COSA The driver will be compiled as a module: the module will be called cosa. -config DSCC4 - tristate "Etinc PCISYNC serial board support" - depends on WAN && PCI && m - help - Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens) - DSCC4 chipset. - - This is supposed to work with the four port card. Take a look at - <http://www.cogenit.fr/dscc4/> for further information about the - driver. - - To compile this driver as a module, choose M here: the - module will be called dscc4. - -config DSCC4_PCISYNC - bool "Etinc PCISYNC features" - depends on DSCC4 - help - Due to Etinc's design choice for its PCISYNC cards, some operations - are only allowed on specific ports of the DSCC4. This option is the - only way for the driver to know that it shouldn't return a success - code for these operations. - - Please say Y if your card is an Etinc's PCISYNC. - -config DSCC4_PCI_RST - bool "Hard reset support" - depends on DSCC4 - help - Various DSCC4 bugs forbid any reliable software reset of the ASIC. - As a replacement, some vendors provide a way to assert the PCI #RST - pin of DSCC4 through the GPIO port of the card. If you choose Y, - the driver will make use of this feature before module removal - (i.e. rmmod). The feature is known to be available on Commtech's - cards. Contact your manufacturer for details. - - Say Y if your card supports this feature. - # # Lan Media's board. Currently 1000, 1200, 5200, 5245 # @@ -127,7 +89,7 @@ config LANMEDIA # There is no way to detect a Sealevel board. Force it modular config SEALEVEL_4021 tristate "Sealevel Systems 4021 support" - depends on WAN && ISA && m && ISA_DMA_API + depends on WAN && ISA && m && ISA_DMA_API && INET help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. @@ -154,7 +116,7 @@ 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. @@ -162,7 +124,7 @@ config HDLC_RAW 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 @@ -173,7 +135,7 @@ 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. @@ -181,7 +143,7 @@ config HDLC_CISCO 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. @@ -189,7 +151,7 @@ config HDLC_FR 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. @@ -197,7 +159,7 @@ config HDLC_PPP 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. @@ -323,6 +285,44 @@ config FARSYNC To compile this driver as a module, choose M here: the module will be called farsync. +config DSCC4 + tristate "Etinc PCISYNC serial board support" + depends on HDLC && PCI && m + help + Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens) + DSCC4 chipset. + + This is supposed to work with the four port card. Take a look at + <http://www.cogenit.fr/dscc4/> for further information about the + driver. + + To compile this driver as a module, choose M here: the + module will be called dscc4. + +config DSCC4_PCISYNC + bool "Etinc PCISYNC features" + depends on DSCC4 + help + Due to Etinc's design choice for its PCISYNC cards, some operations + are only allowed on specific ports of the DSCC4. This option is the + only way for the driver to know that it shouldn't return a success + code for these operations. + + Please say Y if your card is an Etinc's PCISYNC. + +config DSCC4_PCI_RST + bool "Hard reset support" + depends on DSCC4 + help + Various DSCC4 bugs forbid any reliable software reset of the ASIC. + As a replacement, some vendors provide a way to assert the PCI #RST + pin of DSCC4 through the GPIO port of the card. If you choose Y, + the driver will make use of this feature before module removal + (i.e. rmmod). The feature is known to be available on Commtech's + cards. Contact your manufacturer for details. + + Say Y if your card supports this feature. + config DLCI tristate "Frame Relay DLCI support" depends on WAN @@ -382,7 +382,7 @@ config SDLA # Wan router core. config WAN_ROUTER_DRIVERS - bool "WAN router drivers" + tristate "WAN router drivers" depends on WAN && WAN_ROUTER ---help--- Connect LAN to WAN via Linux box. @@ -393,7 +393,8 @@ config WAN_ROUTER_DRIVERS <file:Documentation/networking/wan-router.txt>. Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all + kernel except for how subordinate drivers may be built: + saying N will just cause the configurator to skip all the questions about WAN router drivers. If unsure, say N. diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index 316ca6869d5..83ec2c87ba3 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -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 @@ -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 diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 1f95b4864ea..6c7dfb50143 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -345,7 +345,7 @@ static void put_driver_status(struct cosa_data *cosa); static void put_driver_status_nolock(struct cosa_data *cosa); /* Interrupt handling */ -static irqreturn_t cosa_interrupt(int irq, void *cosa, struct pt_regs *regs); +static irqreturn_t cosa_interrupt(int irq, void *cosa); /* I/O ops debugging */ #ifdef DEBUG_IO @@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file) unsigned long flags; int n; - if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS) + if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS) >= nr_cards) return -ENODEV; cosa = cosa_cards+n; - if ((n=iminor(file->f_dentry->d_inode) + if ((n=iminor(file->f_path.dentry->d_inode) & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) return -ENODEV; chan = cosa->chan + n; @@ -1972,7 +1972,7 @@ out: spin_unlock_irqrestore(&cosa->lock, flags); } -static irqreturn_t cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs) +static irqreturn_t cosa_interrupt(int irq, void *cosa_) { unsigned status; int count = 0; diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c index a5e7ce1bd16..6e5f1c89851 100644 --- a/drivers/net/wan/cycx_main.c +++ b/drivers/net/wan/cycx_main.c @@ -74,7 +74,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf); static int cycx_wan_shutdown(struct wan_device *wandev); /* Miscellaneous functions */ -static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t cycx_isr(int irq, void *dev_id); /* Global Data * Note: All data must be explicitly initialized!!! @@ -301,11 +301,11 @@ out: return ret; * o acknowledge Cyclom 2X hardware interrupt. * o call protocol-specific interrupt service routine, if any. */ -static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t cycx_isr(int irq, void *dev_id) { - struct cycx_device *card = (struct cycx_device *)dev_id; + struct cycx_device *card = dev_id; - if (!card || card->wandev.state == WAN_UNCONFIGURED) + if (card->wandev.state == WAN_UNCONFIGURED) goto out; if (card->in_isr) { diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index af4d4155905..25021a7992a 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -365,7 +365,7 @@ static int dscc4_init_ring(struct net_device *); static void dscc4_release_ring(struct dscc4_dev_priv *); static void dscc4_timer(unsigned long); static void dscc4_tx_timeout(struct net_device *); -static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs); +static irqreturn_t dscc4_irq(int irq, void *dev_id); static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short); static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *); #ifdef DSCC4_POLLING @@ -1476,7 +1476,7 @@ static int dscc4_set_iface(struct dscc4_dev_priv *dpriv, struct net_device *dev) return ret; } -static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs) +static irqreturn_t dscc4_irq(int irq, void *token) { struct dscc4_dev_priv *root = token; struct dscc4_pci_priv *priv; diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 564351aafa4..c45d6a83339 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -1498,7 +1498,7 @@ do_bottom_half_rx(struct fst_card_info *card) * Dev_id is our fst_card_info pointer */ static irqreturn_t -fst_intr(int irq, void *dev_id, struct pt_regs *regs) +fst_intr(int irq, void *dev_id) { struct fst_card_info *card; struct fst_port_info *port; diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c index dce2bb317b8..8d0a1f2f00e 100644 --- a/drivers/net/wan/hd6457x.c +++ b/drivers/net/wan/hd6457x.c @@ -424,7 +424,7 @@ static inline void sca_tx_intr(port_t *port) -static irqreturn_t sca_intr(int irq, void* dev_id, struct pt_regs *regs) +static irqreturn_t sca_intr(int irq, void* dev_id) { card_t *card = dev_id; int i; diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc.c index 04ca1f7b642..db354e0edbe 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc.c @@ -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 @@ -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> @@ -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) { @@ -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; } @@ -77,8 +79,8 @@ 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); } @@ -86,8 +88,8 @@ static inline void hdlc_proto_start(struct net_device *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); } @@ -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; } @@ -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 @@ -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) @@ -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); @@ -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; @@ -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"); @@ -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), diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index f289daba0c7..b0bc5ddcf1b 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * Cisco HDLC support * - * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 2000 - 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 @@ -34,17 +34,56 @@ #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ +struct hdlc_header { + u8 address; + u8 control; + u16 protocol; +}__attribute__ ((packed)); + + +struct cisco_packet { + u32 type; /* code */ + u32 par1; + u32 par2; + u16 rel; /* reliability */ + u32 time; +}__attribute__ ((packed)); +#define CISCO_PACKET_LEN 18 +#define CISCO_BIG_PACKET_LEN 20 + + +struct cisco_state { + cisco_proto settings; + + struct timer_list timer; + unsigned long last_poll; + int up; + int request_sent; + u32 txseq; /* TX sequence number */ + u32 rxseq; /* RX sequence number */ +}; + + +static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr); + + +static inline struct cisco_state * state(hdlc_device *hdlc) +{ + return(struct cisco_state *)(hdlc->state); +} + + static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, u16 type, void *daddr, void *saddr, unsigned int len) { - hdlc_header *data; + struct hdlc_header *data; #ifdef DEBUG_HARD_HEADER printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name); #endif - skb_push(skb, sizeof(hdlc_header)); - data = (hdlc_header*)skb->data; + skb_push(skb, sizeof(struct hdlc_header)); + data = (struct hdlc_header*)skb->data; if (type == CISCO_KEEPALIVE) data->address = CISCO_MULTICAST; else @@ -52,7 +91,7 @@ static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, data->control = 0; data->protocol = htons(type); - return sizeof(hdlc_header); + return sizeof(struct hdlc_header); } @@ -61,9 +100,10 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, u32 par1, u32 par2) { struct sk_buff *skb; - cisco_packet *data; + struct cisco_packet *data; - skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet)); + skb = dev_alloc_skb(sizeof(struct hdlc_header) + + sizeof(struct cisco_packet)); if (!skb) { printk(KERN_WARNING "%s: Memory squeeze on cisco_keepalive_send()\n", @@ -72,7 +112,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, } skb_reserve(skb, 4); cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); - data = (cisco_packet*)(skb->data + 4); + data = (struct cisco_packet*)(skb->data + 4); data->type = htonl(type); data->par1 = htonl(par1); @@ -81,7 +121,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, /* we will need do_div here if 1000 % HZ != 0 */ data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); - skb_put(skb, sizeof(cisco_packet)); + skb_put(skb, sizeof(struct cisco_packet)); skb->priority = TC_PRIO_CONTROL; skb->dev = dev; skb->nh.raw = skb->data; @@ -93,9 +133,9 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) { - hdlc_header *data = (hdlc_header*)skb->data; + struct hdlc_header *data = (struct hdlc_header*)skb->data; - if (skb->len < sizeof(hdlc_header)) + if (skb->len < sizeof(struct hdlc_header)) return __constant_htons(ETH_P_HDLC); if (data->address != CISCO_MULTICAST && @@ -106,7 +146,7 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) case __constant_htons(ETH_P_IP): case __constant_htons(ETH_P_IPX): case __constant_htons(ETH_P_IPV6): - skb_pull(skb, sizeof(hdlc_header)); + skb_pull(skb, sizeof(struct hdlc_header)); return data->protocol; default: return __constant_htons(ETH_P_HDLC); @@ -118,12 +158,12 @@ static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); - hdlc_header *data = (hdlc_header*)skb->data; - cisco_packet *cisco_data; + struct hdlc_header *data = (struct hdlc_header*)skb->data; + struct cisco_packet *cisco_data; struct in_device *in_dev; - u32 addr, mask; + __be32 addr, mask; - if (skb->len < sizeof(hdlc_header)) + if (skb->len < sizeof(struct hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && @@ -137,15 +177,17 @@ static int cisco_rx(struct sk_buff *skb) return NET_RX_SUCCESS; case CISCO_KEEPALIVE: - if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && - skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { - printk(KERN_INFO "%s: Invalid length of Cisco " - "control packet (%d bytes)\n", - dev->name, skb->len); + if ((skb->len != sizeof(struct hdlc_header) + + CISCO_PACKET_LEN) && + (skb->len != sizeof(struct hdlc_header) + + CISCO_BIG_PACKET_LEN)) { + printk(KERN_INFO "%s: Invalid length of Cisco control" + " packet (%d bytes)\n", dev->name, skb->len); goto rx_error; } - cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); + cisco_data = (struct cisco_packet*)(skb->data + sizeof + (struct hdlc_header)); switch(ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ @@ -178,11 +220,11 @@ static int cisco_rx(struct sk_buff *skb) goto rx_error; case CISCO_KEEPALIVE_REQ: - hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); - if (hdlc->state.cisco.request_sent && - ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { - hdlc->state.cisco.last_poll = jiffies; - if (!hdlc->state.cisco.up) { + state(hdlc)->rxseq = ntohl(cisco_data->par1); + if (state(hdlc)->request_sent && + ntohl(cisco_data->par2) == state(hdlc)->txseq) { + state(hdlc)->last_poll = jiffies; + if (!state(hdlc)->up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; @@ -193,7 +235,7 @@ static int cisco_rx(struct sk_buff *skb) dev->name, days, hrs, min, sec); netif_dormant_off(dev); - hdlc->state.cisco.up = 1; + state(hdlc)->up = 1; } } @@ -208,7 +250,7 @@ static int cisco_rx(struct sk_buff *skb) return NET_RX_DROP; rx_error: - hdlc->stats.rx_errors++; /* Mark error */ + dev_to_desc(dev)->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -220,23 +262,22 @@ static void cisco_timer(unsigned long arg) struct net_device *dev = (struct net_device *)arg; hdlc_device *hdlc = dev_to_hdlc(dev); - if (hdlc->state.cisco.up && - time_after(jiffies, hdlc->state.cisco.last_poll + - hdlc->state.cisco.settings.timeout * HZ)) { - hdlc->state.cisco.up = 0; + if (state(hdlc)->up && + time_after(jiffies, state(hdlc)->last_poll + + state(hdlc)->settings.timeout * HZ)) { + state(hdlc)->up = 0; printk(KERN_INFO "%s: Link down\n", dev->name); netif_dormant_on(dev); } - cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, - ++hdlc->state.cisco.txseq, - hdlc->state.cisco.rxseq); - hdlc->state.cisco.request_sent = 1; - hdlc->state.cisco.timer.expires = jiffies + - hdlc->state.cisco.settings.interval * HZ; - hdlc->state.cisco.timer.function = cisco_timer; - hdlc->state.cisco.timer.data = arg; - add_timer(&hdlc->state.cisco.timer); + cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++state(hdlc)->txseq, + state(hdlc)->rxseq); + state(hdlc)->request_sent = 1; + state(hdlc)->timer.expires = jiffies + + state(hdlc)->settings.interval * HZ; + state(hdlc)->timer.function = cisco_timer; + state(hdlc)->timer.data = arg; + add_timer(&state(hdlc)->timer); } @@ -244,15 +285,15 @@ static void cisco_timer(unsigned long arg) static void cisco_start(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - hdlc->state.cisco.up = 0; - hdlc->state.cisco.request_sent = 0; - hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; - - init_timer(&hdlc->state.cisco.timer); - hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ - hdlc->state.cisco.timer.function = cisco_timer; - hdlc->state.cisco.timer.data = (unsigned long)dev; - add_timer(&hdlc->state.cisco.timer); + state(hdlc)->up = 0; + state(hdlc)->request_sent = 0; + state(hdlc)->txseq = state(hdlc)->rxseq = 0; + + init_timer(&state(hdlc)->timer); + state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/ + state(hdlc)->timer.function = cisco_timer; + state(hdlc)->timer.data = (unsigned long)dev; + add_timer(&state(hdlc)->timer); } @@ -260,15 +301,24 @@ static void cisco_start(struct net_device *dev) static void cisco_stop(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - del_timer_sync(&hdlc->state.cisco.timer); + del_timer_sync(&state(hdlc)->timer); netif_dormant_on(dev); - hdlc->state.cisco.up = 0; - hdlc->state.cisco.request_sent = 0; + state(hdlc)->up = 0; + state(hdlc)->request_sent = 0; } -int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) +static struct hdlc_proto proto = { + .start = cisco_start, + .stop = cisco_stop, + .type_trans = cisco_type_trans, + .ioctl = cisco_ioctl, + .module = THIS_MODULE, +}; + + +static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) { cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; const size_t size = sizeof(cisco_proto); @@ -278,12 +328,14 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_CISCO; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } - if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) + if (copy_to_user(cisco_s, &state(hdlc)->settings, size)) return -EFAULT; return 0; @@ -302,19 +354,15 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); - if (result) return result; - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.cisco.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + result = attach_hdlc_protocol(dev, &proto, cisco_rx, + sizeof(struct cisco_state)); + if (result) + return result; - hdlc->proto.start = cisco_start; - hdlc->proto.stop = cisco_stop; - hdlc->proto.netif_rx = cisco_rx; - hdlc->proto.type_trans = cisco_type_trans; - hdlc->proto.id = IF_PROTO_CISCO; + memcpy(&state(hdlc)->settings, &new_settings, size); dev->hard_start_xmit = hdlc->xmit; dev->hard_header = cisco_hard_header; dev->hard_header_cache = NULL; @@ -327,3 +375,25 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("Cisco HDLC protocol support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 7bb737bbdeb..b45ab680d2d 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * Frame Relay support * - * 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 @@ -52,6 +52,8 @@ #undef DEBUG_PKT #undef DEBUG_ECN #undef DEBUG_LINK +#undef DEBUG_PROTO +#undef DEBUG_PVC #define FR_UI 0x03 #define FR_PAD 0x00 @@ -115,13 +117,53 @@ typedef struct { }__attribute__ ((packed)) fr_hdr; +typedef struct pvc_device_struct { + struct net_device *frad; + struct net_device *main; + struct net_device *ether; /* bridged Ethernet interface */ + struct pvc_device_struct *next; /* Sorted in ascending DLCI order */ + int dlci; + int open_count; + + struct { + unsigned int new: 1; + unsigned int active: 1; + unsigned int exist: 1; + unsigned int deleted: 1; + unsigned int fecn: 1; + unsigned int becn: 1; + unsigned int bandwidth; /* Cisco LMI reporting only */ + }state; +}pvc_device; + + +struct frad_state { + fr_proto settings; + pvc_device *first_pvc; + int dce_pvc_count; + + struct timer_list timer; + unsigned long last_poll; + int reliable; + int dce_changed; + int request; + int fullrep_sent; + u32 last_errors; /* last errors bit list */ + u8 n391cnt; + u8 txseq; /* TX sequence number */ + u8 rxseq; /* RX sequence number */ +}; + + +static int fr_ioctl(struct net_device *dev, struct ifreq *ifr); + + static inline u16 q922_to_dlci(u8 *hdr) { return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); } - static inline void dlci_to_q922(u8 *hdr, u16 dlci) { hdr[0] = (dlci >> 2) & 0xFC; @@ -129,10 +171,21 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci) } +static inline struct frad_state * state(hdlc_device *hdlc) +{ + return(struct frad_state *)(hdlc->state); +} + + +static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) +{ + return dev->priv; +} + static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) { - pvc_device *pvc = hdlc->state.fr.first_pvc; + pvc_device *pvc = state(hdlc)->first_pvc; while (pvc) { if (pvc->dlci == dlci) @@ -146,10 +199,10 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) } -static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) +static pvc_device* add_pvc(struct net_device *dev, u16 dlci) { hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; + pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc; while (*pvc_p) { if ((*pvc_p)->dlci == dlci) @@ -160,12 +213,15 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) } pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); +#ifdef DEBUG_PVC + printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev); +#endif if (!pvc) return NULL; memset(pvc, 0, sizeof(pvc_device)); pvc->dlci = dlci; - pvc->master = dev; + pvc->frad = dev; pvc->next = *pvc_p; /* Put it in the chain */ *pvc_p = pvc; return pvc; @@ -174,7 +230,7 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) static inline int pvc_is_used(pvc_device *pvc) { - return pvc->main != NULL || pvc->ether != NULL; + return pvc->main || pvc->ether; } @@ -200,11 +256,14 @@ static inline void pvc_carrier(int on, pvc_device *pvc) static inline void delete_unused_pvcs(hdlc_device *hdlc) { - pvc_device **pvc_p = &hdlc->state.fr.first_pvc; + pvc_device **pvc_p = &state(hdlc)->first_pvc; while (*pvc_p) { if (!pvc_is_used(*pvc_p)) { pvc_device *pvc = *pvc_p; +#ifdef DEBUG_PVC + printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc); +#endif *pvc_p = pvc->next; kfree(pvc); continue; @@ -295,16 +354,16 @@ static int pvc_open(struct net_device *dev) { pvc_device *pvc = dev_to_pvc(dev); - if ((pvc->master->flags & IFF_UP) == 0) - return -EIO; /* Master must be UP in order to activate PVC */ + if ((pvc->frad->flags & IFF_UP) == 0) + return -EIO; /* Frad must be UP in order to activate PVC */ if (pvc->open_count++ == 0) { - hdlc_device *hdlc = dev_to_hdlc(pvc->master); - if (hdlc->state.fr.settings.lmi == LMI_NONE) - pvc->state.active = netif_carrier_ok(pvc->master); + hdlc_device *hdlc = dev_to_hdlc(pvc->frad); + if (state(hdlc)->settings.lmi == LMI_NONE) + pvc->state.active = netif_carrier_ok(pvc->frad); pvc_carrier(pvc->state.active, pvc); - hdlc->state.fr.dce_changed = 1; + state(hdlc)->dce_changed = 1; } return 0; } @@ -316,12 +375,12 @@ static int pvc_close(struct net_device *dev) pvc_device *pvc = dev_to_pvc(dev); if (--pvc->open_count == 0) { - hdlc_device *hdlc = dev_to_hdlc(pvc->master); - if (hdlc->state.fr.settings.lmi == LMI_NONE) + hdlc_device *hdlc = dev_to_hdlc(pvc->frad); + if (state(hdlc)->settings.lmi == LMI_NONE) pvc->state.active = 0; - if (hdlc->state.fr.settings.dce) { - hdlc->state.fr.dce_changed = 1; + if (state(hdlc)->settings.dce) { + state(hdlc)->dce_changed = 1; pvc->state.active = 0; } } @@ -348,7 +407,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } info.dlci = pvc->dlci; - memcpy(info.master, pvc->master->name, IFNAMSIZ); + memcpy(info.master, pvc->frad->name, IFNAMSIZ); if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, &info, sizeof(info))) return -EFAULT; @@ -361,7 +420,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) { - return netdev_priv(dev); + return &dev_to_desc(dev)->stats; } @@ -393,7 +452,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) stats->tx_packets++; if (pvc->state.fecn) /* TX Congestion counter */ stats->tx_compressed++; - skb->dev = pvc->master; + skb->dev = pvc->frad; dev_queue_xmit(skb); return 0; } @@ -419,7 +478,7 @@ static int pvc_change_mtu(struct net_device *dev, int new_mtu) static inline void fr_log_dlci_active(pvc_device *pvc) { printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", - pvc->master->name, + pvc->frad->name, pvc->dlci, pvc->main ? pvc->main->name : "", pvc->main && pvc->ether ? " " : "", @@ -438,21 +497,20 @@ static inline u8 fr_lmi_nextseq(u8 x) } - static void fr_lmi_send(struct net_device *dev, int fullrep) { hdlc_device *hdlc = dev_to_hdlc(dev); struct sk_buff *skb; - pvc_device *pvc = hdlc->state.fr.first_pvc; - int lmi = hdlc->state.fr.settings.lmi; - int dce = hdlc->state.fr.settings.dce; + pvc_device *pvc = state(hdlc)->first_pvc; + int lmi = state(hdlc)->settings.lmi; + int dce = state(hdlc)->settings.dce; int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; int stat_len = (lmi == LMI_CISCO) ? 6 : 3; u8 *data; int i = 0; if (dce && fullrep) { - len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); + len += state(hdlc)->dce_pvc_count * (2 + stat_len); if (len > HDLC_MAX_MRU) { printk(KERN_WARNING "%s: Too many PVCs while sending " "LMI full report\n", dev->name); @@ -486,8 +544,9 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; data[i++] = LMI_INTEG_LEN; - data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); - data[i++] = hdlc->state.fr.rxseq; + data[i++] = state(hdlc)->txseq = + fr_lmi_nextseq(state(hdlc)->txseq); + data[i++] = state(hdlc)->rxseq; if (dce && fullrep) { while (pvc) { @@ -496,7 +555,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) data[i++] = stat_len; /* LMI start/restart */ - if (hdlc->state.fr.reliable && !pvc->state.exist) { + if (state(hdlc)->reliable && !pvc->state.exist) { pvc->state.exist = pvc->state.new = 1; fr_log_dlci_active(pvc); } @@ -541,15 +600,15 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) static void fr_set_link_state(int reliable, struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc = hdlc->state.fr.first_pvc; + pvc_device *pvc = state(hdlc)->first_pvc; - hdlc->state.fr.reliable = reliable; + state(hdlc)->reliable = reliable; if (reliable) { netif_dormant_off(dev); - hdlc->state.fr.n391cnt = 0; /* Request full status */ - hdlc->state.fr.dce_changed = 1; + state(hdlc)->n391cnt = 0; /* Request full status */ + state(hdlc)->dce_changed = 1; - if (hdlc->state.fr.settings.lmi == LMI_NONE) { + if (state(hdlc)->settings.lmi == LMI_NONE) { while (pvc) { /* Activate all PVCs */ pvc_carrier(1, pvc); pvc->state.exist = pvc->state.active = 1; @@ -563,7 +622,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev) pvc_carrier(0, pvc); pvc->state.exist = pvc->state.active = 0; pvc->state.new = 0; - if (!hdlc->state.fr.settings.dce) + if (!state(hdlc)->settings.dce) pvc->state.bandwidth = 0; pvc = pvc->next; } @@ -571,7 +630,6 @@ static void fr_set_link_state(int reliable, struct net_device *dev) } - static void fr_timer(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; @@ -579,62 +637,61 @@ static void fr_timer(unsigned long arg) int i, cnt = 0, reliable; u32 list; - if (hdlc->state.fr.settings.dce) { - reliable = hdlc->state.fr.request && - time_before(jiffies, hdlc->state.fr.last_poll + - hdlc->state.fr.settings.t392 * HZ); - hdlc->state.fr.request = 0; + if (state(hdlc)->settings.dce) { + reliable = state(hdlc)->request && + time_before(jiffies, state(hdlc)->last_poll + + state(hdlc)->settings.t392 * HZ); + state(hdlc)->request = 0; } else { - hdlc->state.fr.last_errors <<= 1; /* Shift the list */ - if (hdlc->state.fr.request) { - if (hdlc->state.fr.reliable) + state(hdlc)->last_errors <<= 1; /* Shift the list */ + if (state(hdlc)->request) { + if (state(hdlc)->reliable) printk(KERN_INFO "%s: No LMI status reply " "received\n", dev->name); - hdlc->state.fr.last_errors |= 1; + state(hdlc)->last_errors |= 1; } - list = hdlc->state.fr.last_errors; - for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1) + list = state(hdlc)->last_errors; + for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1) cnt += (list & 1); /* errors count */ - reliable = (cnt < hdlc->state.fr.settings.n392); + reliable = (cnt < state(hdlc)->settings.n392); } - if (hdlc->state.fr.reliable != reliable) { + if (state(hdlc)->reliable != reliable) { printk(KERN_INFO "%s: Link %sreliable\n", dev->name, reliable ? "" : "un"); fr_set_link_state(reliable, dev); } - if (hdlc->state.fr.settings.dce) - hdlc->state.fr.timer.expires = jiffies + - hdlc->state.fr.settings.t392 * HZ; + if (state(hdlc)->settings.dce) + state(hdlc)->timer.expires = jiffies + + state(hdlc)->settings.t392 * HZ; else { - if (hdlc->state.fr.n391cnt) - hdlc->state.fr.n391cnt--; + if (state(hdlc)->n391cnt) + state(hdlc)->n391cnt--; - fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); + fr_lmi_send(dev, state(hdlc)->n391cnt == 0); - hdlc->state.fr.last_poll = jiffies; - hdlc->state.fr.request = 1; - hdlc->state.fr.timer.expires = jiffies + - hdlc->state.fr.settings.t391 * HZ; + state(hdlc)->last_poll = jiffies; + state(hdlc)->request = 1; + state(hdlc)->timer.expires = jiffies + + state(hdlc)->settings.t391 * HZ; } - hdlc->state.fr.timer.function = fr_timer; - hdlc->state.fr.timer.data = arg; - add_timer(&hdlc->state.fr.timer); + state(hdlc)->timer.function = fr_timer; + state(hdlc)->timer.data = arg; + add_timer(&state(hdlc)->timer); } - static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) { hdlc_device *hdlc = dev_to_hdlc(dev); pvc_device *pvc; u8 rxseq, txseq; - int lmi = hdlc->state.fr.settings.lmi; - int dce = hdlc->state.fr.settings.dce; + int lmi = state(hdlc)->settings.lmi; + int dce = state(hdlc)->settings.dce; int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : @@ -645,8 +702,8 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : NLPID_CCITT_ANSI_LMI)) { - printk(KERN_INFO "%s: Received non-LMI frame with LMI" - " DLCI\n", dev->name); + printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n", + dev->name); return 1; } @@ -706,53 +763,53 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) } i++; - hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ + state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */ rxseq = skb->data[i++]; /* Should confirm our sequence */ - txseq = hdlc->state.fr.txseq; + txseq = state(hdlc)->txseq; if (dce) - hdlc->state.fr.last_poll = jiffies; + state(hdlc)->last_poll = jiffies; error = 0; - if (!hdlc->state.fr.reliable) + if (!state(hdlc)->reliable) error = 1; - if (rxseq == 0 || rxseq != txseq) { - hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */ + if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */ + state(hdlc)->n391cnt = 0; error = 1; } if (dce) { - if (hdlc->state.fr.fullrep_sent && !error) { + if (state(hdlc)->fullrep_sent && !error) { /* Stop sending full report - the last one has been confirmed by DTE */ - hdlc->state.fr.fullrep_sent = 0; - pvc = hdlc->state.fr.first_pvc; + state(hdlc)->fullrep_sent = 0; + pvc = state(hdlc)->first_pvc; while (pvc) { if (pvc->state.new) { pvc->state.new = 0; /* Tell DTE that new PVC is now active */ - hdlc->state.fr.dce_changed = 1; + state(hdlc)->dce_changed = 1; } pvc = pvc->next; } } - if (hdlc->state.fr.dce_changed) { + if (state(hdlc)->dce_changed) { reptype = LMI_FULLREP; - hdlc->state.fr.fullrep_sent = 1; - hdlc->state.fr.dce_changed = 0; + state(hdlc)->fullrep_sent = 1; + state(hdlc)->dce_changed = 0; } - hdlc->state.fr.request = 1; /* got request */ + state(hdlc)->request = 1; /* got request */ fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); return 0; } /* DTE */ - hdlc->state.fr.request = 0; /* got response, no request pending */ + state(hdlc)->request = 0; /* got response, no request pending */ if (error) return 0; @@ -760,7 +817,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (reptype != LMI_FULLREP) return 0; - pvc = hdlc->state.fr.first_pvc; + pvc = state(hdlc)->first_pvc; while (pvc) { pvc->state.deleted = 1; @@ -827,7 +884,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) i += stat_len; } - pvc = hdlc->state.fr.first_pvc; + pvc = state(hdlc)->first_pvc; while (pvc) { if (pvc->state.deleted && pvc->state.exist) { @@ -841,17 +898,16 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) } /* Next full report after N391 polls */ - hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391; + state(hdlc)->n391cnt = state(hdlc)->settings.n391; return 0; } - static int fr_rx(struct sk_buff *skb) { - struct net_device *ndev = skb->dev; - hdlc_device *hdlc = dev_to_hdlc(ndev); + struct net_device *frad = skb->dev; + hdlc_device *hdlc = dev_to_hdlc(frad); fr_hdr *fh = (fr_hdr*)skb->data; u8 *data = skb->data; u16 dlci; @@ -864,11 +920,11 @@ static int fr_rx(struct sk_buff *skb) dlci = q922_to_dlci(skb->data); if ((dlci == LMI_CCITT_ANSI_DLCI && - (hdlc->state.fr.settings.lmi == LMI_ANSI || - hdlc->state.fr.settings.lmi == LMI_CCITT)) || + (state(hdlc)->settings.lmi == LMI_ANSI || + state(hdlc)->settings.lmi == LMI_CCITT)) || (dlci == LMI_CISCO_DLCI && - hdlc->state.fr.settings.lmi == LMI_CISCO)) { - if (fr_lmi_recv(ndev, skb)) + state(hdlc)->settings.lmi == LMI_CISCO)) { + if (fr_lmi_recv(frad, skb)) goto rx_error; dev_kfree_skb_any(skb); return NET_RX_SUCCESS; @@ -878,7 +934,7 @@ static int fr_rx(struct sk_buff *skb) if (!pvc) { #ifdef DEBUG_PKT printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", - ndev->name, dlci); + frad->name, dlci); #endif dev_kfree_skb_any(skb); return NET_RX_DROP; @@ -886,7 +942,7 @@ static int fr_rx(struct sk_buff *skb) if (pvc->state.fecn != fh->fecn) { #ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, + printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name, dlci, fh->fecn ? "N" : "FF"); #endif pvc->state.fecn ^= 1; @@ -894,7 +950,7 @@ static int fr_rx(struct sk_buff *skb) if (pvc->state.becn != fh->becn) { #ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, + printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name, dlci, fh->becn ? "N" : "FF"); #endif pvc->state.becn ^= 1; @@ -902,7 +958,7 @@ static int fr_rx(struct sk_buff *skb) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - hdlc->stats.rx_dropped++; + dev_to_desc(frad)->stats.rx_dropped++; return NET_RX_DROP; } @@ -938,13 +994,13 @@ static int fr_rx(struct sk_buff *skb) default: printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " - "PID=%x\n", ndev->name, oui, pid); + "PID=%x\n", frad->name, oui, pid); dev_kfree_skb_any(skb); return NET_RX_DROP; } } else { printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " - "length = %i\n", ndev->name, data[3], skb->len); + "length = %i\n", frad->name, data[3], skb->len); dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -964,7 +1020,7 @@ static int fr_rx(struct sk_buff *skb) } rx_error: - hdlc->stats.rx_errors++; /* Mark error */ + dev_to_desc(frad)->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -977,44 +1033,42 @@ static void fr_start(struct net_device *dev) #ifdef DEBUG_LINK printk(KERN_DEBUG "fr_start\n"); #endif - if (hdlc->state.fr.settings.lmi != LMI_NONE) { - hdlc->state.fr.reliable = 0; - hdlc->state.fr.dce_changed = 1; - hdlc->state.fr.request = 0; - hdlc->state.fr.fullrep_sent = 0; - hdlc->state.fr.last_errors = 0xFFFFFFFF; - hdlc->state.fr.n391cnt = 0; - hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0; - - init_timer(&hdlc->state.fr.timer); + if (state(hdlc)->settings.lmi != LMI_NONE) { + state(hdlc)->reliable = 0; + state(hdlc)->dce_changed = 1; + state(hdlc)->request = 0; + state(hdlc)->fullrep_sent = 0; + state(hdlc)->last_errors = 0xFFFFFFFF; + state(hdlc)->n391cnt = 0; + state(hdlc)->txseq = state(hdlc)->rxseq = 0; + + init_timer(&state(hdlc)->timer); /* First poll after 1 s */ - hdlc->state.fr.timer.expires = jiffies + HZ; - hdlc->state.fr.timer.function = fr_timer; - hdlc->state.fr.timer.data = (unsigned long)dev; - add_timer(&hdlc->state.fr.timer); + state(hdlc)->timer.expires = jiffies + HZ; + state(hdlc)->timer.function = fr_timer; + state(hdlc)->timer.data = (unsigned long)dev; + add_timer(&state(hdlc)->timer); } else fr_set_link_state(1, dev); } - static void fr_stop(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "fr_stop\n"); #endif - if (hdlc->state.fr.settings.lmi != LMI_NONE) - del_timer_sync(&hdlc->state.fr.timer); + if (state(hdlc)->settings.lmi != LMI_NONE) + del_timer_sync(&state(hdlc)->timer); fr_set_link_state(0, dev); } - static void fr_close(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc = hdlc->state.fr.first_pvc; + pvc_device *pvc = state(hdlc)->first_pvc; while (pvc) { /* Shutdown all PVCs for this FRAD */ if (pvc->main) @@ -1025,7 +1079,8 @@ static void fr_close(struct net_device *dev) } } -static void dlci_setup(struct net_device *dev) + +static void pvc_setup(struct net_device *dev) { dev->type = ARPHRD_DLCI; dev->flags = IFF_POINTOPOINT; @@ -1033,9 +1088,9 @@ static void dlci_setup(struct net_device *dev) dev->addr_len = 2; } -static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) +static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) { - hdlc_device *hdlc = dev_to_hdlc(master); + hdlc_device *hdlc = dev_to_hdlc(frad); pvc_device *pvc = NULL; struct net_device *dev; int result, used; @@ -1044,9 +1099,9 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) if (type == ARPHRD_ETHER) prefix = "pvceth%d"; - if ((pvc = add_pvc(master, dlci)) == NULL) { + if ((pvc = add_pvc(frad, dlci)) == NULL) { printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", - master->name); + frad->name); return -ENOBUFS; } @@ -1060,11 +1115,11 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) "pvceth%d", ether_setup); else dev = alloc_netdev(sizeof(struct net_device_stats), - "pvc%d", dlci_setup); + "pvc%d", pvc_setup); if (!dev) { printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", - master->name); + frad->name); delete_unused_pvcs(hdlc); return -ENOBUFS; } @@ -1102,8 +1157,8 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) dev->destructor = free_netdev; *get_dev_p(pvc, type) = dev; if (!used) { - hdlc->state.fr.dce_changed = 1; - hdlc->state.fr.dce_pvc_count++; + state(hdlc)->dce_changed = 1; + state(hdlc)->dce_pvc_count++; } return 0; } @@ -1128,8 +1183,8 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) *get_dev_p(pvc, type) = NULL; if (!pvc_is_used(pvc)) { - hdlc->state.fr.dce_pvc_count--; - hdlc->state.fr.dce_changed = 1; + state(hdlc)->dce_pvc_count--; + state(hdlc)->dce_changed = 1; } delete_unused_pvcs(hdlc); return 0; @@ -1137,14 +1192,13 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) -static void fr_destroy(hdlc_device *hdlc) +static void fr_destroy(struct net_device *frad) { - pvc_device *pvc; - - pvc = hdlc->state.fr.first_pvc; - hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ - hdlc->state.fr.dce_pvc_count = 0; - hdlc->state.fr.dce_changed = 1; + hdlc_device *hdlc = dev_to_hdlc(frad); + pvc_device *pvc = state(hdlc)->first_pvc; + state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */ + state(hdlc)->dce_pvc_count = 0; + state(hdlc)->dce_changed = 1; while (pvc) { pvc_device *next = pvc->next; @@ -1161,8 +1215,17 @@ static void fr_destroy(hdlc_device *hdlc) } +static struct hdlc_proto proto = { + .close = fr_close, + .start = fr_start, + .stop = fr_stop, + .detach = fr_destroy, + .ioctl = fr_ioctl, + .module = THIS_MODULE, +}; + -int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) +static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) { fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; const size_t size = sizeof(fr_proto); @@ -1173,12 +1236,14 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_FR; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } - if (copy_to_user(fr_s, &hdlc->state.fr.settings, size)) + if (copy_to_user(fr_s, &state(hdlc)->settings, size)) return -EFAULT; return 0; @@ -1213,20 +1278,16 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; - if (hdlc->proto.id != IF_PROTO_FR) { - hdlc_proto_detach(hdlc); - hdlc->state.fr.first_pvc = NULL; - hdlc->state.fr.dce_pvc_count = 0; + if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ + result = attach_hdlc_protocol(dev, &proto, fr_rx, + sizeof(struct frad_state)); + if (result) + return result; + state(hdlc)->first_pvc = NULL; + state(hdlc)->dce_pvc_count = 0; } - memcpy(&hdlc->state.fr.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.close = fr_close; - hdlc->proto.start = fr_start; - hdlc->proto.stop = fr_stop; - hdlc->proto.detach = fr_destroy; - hdlc->proto.netif_rx = fr_rx; - hdlc->proto.id = IF_PROTO_FR; + memcpy(&state(hdlc)->settings, &new_settings, size); + dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_FRAD; @@ -1238,6 +1299,9 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) case IF_PROTO_FR_DEL_PVC: case IF_PROTO_FR_ADD_ETH_PVC: case IF_PROTO_FR_DEL_ETH_PVC: + if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ + return -EINVAL; + if(!capable(CAP_NET_ADMIN)) return -EPERM; @@ -1263,3 +1327,24 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index fbaab5bf71e..e9f717070fd 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * Point-to-point protocol support * - * Copyright (C) 1999 - 2003 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 @@ -22,6 +22,21 @@ #include <linux/lapb.h> #include <linux/rtnetlink.h> #include <linux/hdlc.h> +#include <net/syncppp.h> + +struct ppp_state { + struct ppp_device pppdev; + struct ppp_device *syncppp_ptr; + int (*old_change_mtu)(struct net_device *dev, int new_mtu); +}; + +static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr); + + +static inline struct ppp_state* state(hdlc_device *hdlc) +{ + return(struct ppp_state *)(hdlc->state); +} static int ppp_open(struct net_device *dev) @@ -30,16 +45,16 @@ static int ppp_open(struct net_device *dev) void *old_ioctl; int result; - dev->priv = &hdlc->state.ppp.syncppp_ptr; - hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; - hdlc->state.ppp.pppdev.dev = dev; + dev->priv = &state(hdlc)->syncppp_ptr; + state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev; + state(hdlc)->pppdev.dev = dev; old_ioctl = dev->do_ioctl; - hdlc->state.ppp.old_change_mtu = dev->change_mtu; - sppp_attach(&hdlc->state.ppp.pppdev); + state(hdlc)->old_change_mtu = dev->change_mtu; + sppp_attach(&state(hdlc)->pppdev); /* sppp_attach nukes them. We don't need syncppp's ioctl */ dev->do_ioctl = old_ioctl; - hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; + state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO; dev->type = ARPHRD_PPP; result = sppp_open(dev); if (result) { @@ -59,7 +74,7 @@ static void ppp_close(struct net_device *dev) sppp_close(dev); sppp_detach(dev); dev->rebuild_header = NULL; - dev->change_mtu = hdlc->state.ppp.old_change_mtu; + dev->change_mtu = state(hdlc)->old_change_mtu; dev->mtu = HDLC_MAX_MTU; dev->hard_header_len = 16; } @@ -73,13 +88,24 @@ static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) -int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) +static struct hdlc_proto proto = { + .open = ppp_open, + .close = ppp_close, + .type_trans = ppp_type_trans, + .ioctl = ppp_ioctl, + .module = THIS_MODULE, +}; + + +static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) { hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_PPP; return 0; /* return protocol only, no settable parameters */ @@ -96,13 +122,10 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; - hdlc_proto_detach(hdlc); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.open = ppp_open; - hdlc->proto.close = ppp_close; - hdlc->proto.type_trans = ppp_type_trans; - hdlc->proto.id = IF_PROTO_PPP; + result = attach_hdlc_protocol(dev, &proto, NULL, + sizeof(struct ppp_state)); + if (result) + return result; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_PPP; @@ -113,3 +136,25 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("PPP protocol support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index f15aa6ba77f..fe3cae5c6b9 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * HDLC support * - * Copyright (C) 1999 - 2003 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 @@ -24,6 +24,8 @@ #include <linux/hdlc.h> +static int raw_ioctl(struct net_device *dev, struct ifreq *ifr); + static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) { return __constant_htons(ETH_P_IP); @@ -31,7 +33,14 @@ static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) -int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) +static struct hdlc_proto proto = { + .type_trans = raw_type_trans, + .ioctl = raw_ioctl, + .module = THIS_MODULE, +}; + + +static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) { raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); @@ -41,12 +50,14 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_HDLC; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } - if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) + if (copy_to_user(raw_s, hdlc->state, size)) return -EFAULT; return 0; @@ -71,12 +82,11 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.type_trans = raw_type_trans; - hdlc->proto.id = IF_PROTO_HDLC; + result = attach_hdlc_protocol(dev, &proto, NULL, + sizeof(raw_hdlc_proto)); + if (result) + return result; + memcpy(hdlc->state, &new_settings, size); dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_RAWHDLC; @@ -88,3 +98,25 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index d1884987f94..1a69a9aaa9b 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * HDLC Ethernet emulation support * - * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 2002-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 @@ -25,6 +25,7 @@ #include <linux/etherdevice.h> #include <linux/hdlc.h> +static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr); static int eth_tx(struct sk_buff *skb, struct net_device *dev) { @@ -44,7 +45,14 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev) } -int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) +static struct hdlc_proto proto = { + .type_trans = eth_type_trans, + .ioctl = raw_eth_ioctl, + .module = THIS_MODULE, +}; + + +static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) { raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); @@ -56,12 +64,14 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } - if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) + if (copy_to_user(raw_s, hdlc->state, size)) return -EFAULT; return 0; @@ -86,12 +96,11 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.type_trans = eth_type_trans; - hdlc->proto.id = IF_PROTO_HDLC_ETH; + result = attach_hdlc_protocol(dev, &proto, NULL, + sizeof(raw_hdlc_proto)); + if (result) + return result; + memcpy(hdlc->state, &new_settings, size); dev->hard_start_xmit = eth_tx; old_ch_mtu = dev->change_mtu; old_qlen = dev->tx_queue_len; @@ -106,3 +115,25 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index a867fb411f8..e4bb9f8ad43 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * X.25 support * - * Copyright (C) 1999 - 2003 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 @@ -25,6 +25,8 @@ #include <net/x25device.h> +static int x25_ioctl(struct net_device *dev, struct ifreq *ifr); + /* These functions are callbacks called by LAPB layer */ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) @@ -162,30 +164,39 @@ static void x25_close(struct net_device *dev) static int x25_rx(struct sk_buff *skb) { - hdlc_device *hdlc = dev_to_hdlc(skb->dev); + struct hdlc_device_desc *desc = dev_to_desc(skb->dev); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - hdlc->stats.rx_dropped++; + desc->stats.rx_dropped++; return NET_RX_DROP; } if (lapb_data_received(skb->dev, skb) == LAPB_OK) return NET_RX_SUCCESS; - hdlc->stats.rx_errors++; + desc->stats.rx_errors++; dev_kfree_skb_any(skb); return NET_RX_DROP; } +static struct hdlc_proto proto = { + .open = x25_open, + .close = x25_close, + .ioctl = x25_ioctl, + .module = THIS_MODULE, +}; + -int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) +static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) { hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: + if (dev_to_hdlc(dev)->proto != &proto) + return -EINVAL; ifr->ifr_settings.type = IF_PROTO_X25; return 0; /* return protocol only, no settable parameters */ @@ -200,14 +211,9 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; - hdlc_proto_detach(hdlc); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.open = x25_open; - hdlc->proto.close = x25_close; - hdlc->proto.netif_rx = x25_rx; - hdlc->proto.type_trans = NULL; - hdlc->proto.id = IF_PROTO_X25; + if ((result = attach_hdlc_protocol(dev, &proto, + x25_rx, 0)) != 0) + return result; dev->hard_start_xmit = x25_xmit; dev->hard_header = NULL; dev->type = ARPHRD_X25; @@ -218,3 +224,25 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) return -EINVAL; } + + +static int __init mod_init(void) +{ + register_hdlc_protocol(&proto); + return 0; +} + + + +static void __exit mod_exit(void) +{ + unregister_hdlc_protocol(&proto); +} + + +module_init(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("X.25 protocol support for generic HDLC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 7b5d81deb02..2b54f1bc3a0 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -100,7 +100,7 @@ static int lmc_rx (struct net_device *dev); static int lmc_open(struct net_device *dev); static int lmc_close(struct net_device *dev); static struct net_device_stats *lmc_get_stats(struct net_device *dev); -static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static irqreturn_t lmc_interrupt(int irq, void *dev_instance); static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size); static void lmc_softreset(lmc_softc_t * const); static void lmc_running_reset(struct net_device *dev); @@ -1273,7 +1273,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ /* Interrupt handling routine. This will take an incoming packet, or clean * up after a trasmit. */ -static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/ +static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ { struct net_device *dev = (struct net_device *) dev_instance; lmc_softc_t *sc; diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index dcf46add3ad..5c322dfb79f 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -500,7 +500,7 @@ static int __init n2_init(void) #ifdef MODULE printk(KERN_INFO "n2: no card initialized\n"); #endif - return -ENOSYS; /* no parameters specified, abort */ + return -EINVAL; /* no parameters specified, abort */ } printk(KERN_INFO "%s\n", version); @@ -538,11 +538,11 @@ static int __init n2_init(void) n2_run(io, irq, ram, valid[0], valid[1]); if (*hw == '\x0') - return first_card ? 0 : -ENOSYS; + return first_card ? 0 : -EINVAL; }while(*hw++ == ':'); printk(KERN_ERR "n2: invalid hardware parameters\n"); - return first_card ? 0 : -ENOSYS; + return first_card ? 0 : -EINVAL; } diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h index 2024b26b99e..63e9fcf31fb 100644 --- a/drivers/net/wan/pc300.h +++ b/drivers/net/wan/pc300.h @@ -100,6 +100,7 @@ #define _PC300_H #include <linux/hdlc.h> +#include <net/syncppp.h> #include "hd64572.h" #include "pc300-falc-lh.h" diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 56e69403d17..36d1c3ff707 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -284,7 +284,7 @@ static void rx_dma_buf_pt_init(pc300_t *, int); static void rx_dma_buf_init(pc300_t *, int); static void tx_dma_buf_check(pc300_t *, int); static void rx_dma_buf_check(pc300_t *, int); -static irqreturn_t cpc_intr(int, void *, struct pt_regs *); +static irqreturn_t cpc_intr(int, void *); static struct net_device_stats *cpc_get_stats(struct net_device *); static int clock_rate_calc(uclong, uclong, int *); static uclong detect_ram(pc300_t *); @@ -2016,7 +2016,6 @@ static void sca_intr(pc300_t * card) pc300ch_t *chan = &card->chan[ch]; pc300dev_t *d = &chan->d; struct net_device *dev = d->dev; - hdlc_device *hdlc = dev_to_hdlc(dev); spin_lock(&card->card_lock); @@ -2049,8 +2048,8 @@ static void sca_intr(pc300_t * card) } cpc_net_rx(dev); /* Discard invalid frames */ - hdlc->stats.rx_errors++; - hdlc->stats.rx_over_errors++; + hdlc_stats(dev)->rx_errors++; + hdlc_stats(dev)->rx_over_errors++; chan->rx_first_bd = 0; chan->rx_last_bd = N_DMA_RX_BUF - 1; rx_dma_start(card, ch); @@ -2116,8 +2115,8 @@ static void sca_intr(pc300_t * card) card->hw.cpld_reg2) & ~ (CPLD_REG2_FALC_LED1 << (2 * ch))); } - hdlc->stats.tx_errors++; - hdlc->stats.tx_fifo_errors++; + hdlc_stats(dev)->tx_errors++; + hdlc_stats(dev)->tx_fifo_errors++; sca_tx_intr(d); } } @@ -2364,7 +2363,7 @@ static void falc_intr(pc300_t * card) } } -static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t cpc_intr(int irq, void *dev_id) { pc300_t *card; volatile ucchar plx_status; @@ -2534,7 +2533,6 @@ static int cpc_change_mtu(struct net_device *dev, int new_mtu) static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - hdlc_device *hdlc = dev_to_hdlc(dev); pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; @@ -2552,10 +2550,10 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGPC300CONF: #ifdef CONFIG_PC300_MLPPP if (conf->proto != PC300_PROTO_MLPPP) { - conf->proto = hdlc->proto.id; + conf->proto = /* FIXME hdlc->proto.id */ 0; } #else - conf->proto = hdlc->proto.id; + conf->proto = /* FIXME hdlc->proto.id */ 0; #endif memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t)); memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t)); @@ -2588,12 +2586,12 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } else { memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t)); - hdlc->proto.id = conf->proto; + /* FIXME hdlc->proto.id = conf->proto; */ } } #else memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t)); - hdlc->proto.id = conf->proto; + /* FIXME hdlc->proto.id = conf->proto; */ #endif return 0; case SIOCGPC300STATUS: @@ -2606,7 +2604,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGPC300UTILSTATS: { if (!arg) { /* clear statistics */ - memset(&hdlc->stats, 0, sizeof(struct net_device_stats)); + memset(hdlc_stats(dev), 0, sizeof(struct net_device_stats)); if (card->hw.type == PC300_TE) { memset(&chan->falc, 0, sizeof(falc_t)); } @@ -2617,7 +2615,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) pc300stats.hw_type = card->hw.type; pc300stats.line_on = card->chan[ch].d.line_on; pc300stats.line_off = card->chan[ch].d.line_off; - memcpy(&pc300stats.gen_stats, &hdlc->stats, + memcpy(&pc300stats.gen_stats, hdlc_stats(dev), sizeof(struct net_device_stats)); if (card->hw.type == PC300_TE) memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t)); @@ -2869,7 +2867,6 @@ static int ch_config(pc300dev_t * d) uclong clktype = chan->conf.phys_settings.clock_type; ucshort encoding = chan->conf.proto_settings.encoding; ucshort parity = chan->conf.proto_settings.parity; - int tmc, br; ucchar md0, md2; /* Reset the channel */ @@ -2942,8 +2939,12 @@ static int ch_config(pc300dev_t * d) case PC300_RSV: case PC300_X21: if (clktype == CLOCK_INT || clktype == CLOCK_TXINT) { + int tmc, br; + /* Calculate the clkrate parameters */ tmc = clock_rate_calc(clkrate, card->hw.clock, &br); + if (tmc < 0) + return -EIO; cpc_writeb(scabase + M_REG(TMCT, ch), tmc); cpc_writeb(scabase + M_REG(TXS, ch), (TXS_DTRXC | TXS_IBRG | br)); @@ -3099,14 +3100,16 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding, return 0; } -static void cpc_opench(pc300dev_t * d) +static int cpc_opench(pc300dev_t * d) { pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - int ch = chan->channel; + int ch = chan->channel, rc; void __iomem *scabase = card->hw.scabase; - ch_config(d); + rc = ch_config(d); + if (rc) + return rc; rx_config(d); @@ -3115,6 +3118,8 @@ static void cpc_opench(pc300dev_t * d) /* Assert RTS and DTR */ cpc_writeb(scabase + M_REG(CTL, ch), cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR)); + + return 0; } static void cpc_closech(pc300dev_t * d) @@ -3147,7 +3152,6 @@ static void cpc_closech(pc300dev_t * d) int cpc_open(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); pc300dev_t *d = (pc300dev_t *) dev->priv; struct ifreq ifr; int result; @@ -3156,12 +3160,14 @@ int cpc_open(struct net_device *dev) printk("pc300: cpc_open"); #endif +#ifdef FIXME if (hdlc->proto.id == IF_PROTO_PPP) { d->if_ptr = &hdlc->state.ppp.pppdev; } +#endif result = hdlc_open(dev); - if (hdlc->proto.id == IF_PROTO_PPP) { + if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) { dev->priv = d; } if (result) { @@ -3169,14 +3175,20 @@ int cpc_open(struct net_device *dev) } sprintf(ifr.ifr_name, "%s", dev->name); - cpc_opench(d); + result = cpc_opench(d); + if (result) + goto err_out; + netif_start_queue(dev); return 0; + +err_out: + hdlc_close(dev); + return result; } static int cpc_close(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; @@ -3193,7 +3205,7 @@ static int cpc_close(struct net_device *dev) CPC_UNLOCK(card, flags); hdlc_close(dev); - if (hdlc->proto.id == IF_PROTO_PPP) { + if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) { d->if_ptr = NULL; } #ifdef CONFIG_PC300_MLPPP diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 931cbdf6d79..b2a23aed442 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -125,8 +125,8 @@ static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); static void cpc_tty_hangup(struct tty_struct *tty); -static void cpc_tty_rx_work(void *data); -static void cpc_tty_tx_work(void *data); +static void cpc_tty_rx_work(struct work_struct *work); +static void cpc_tty_tx_work(struct work_struct *work); static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len); static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char); @@ -261,8 +261,8 @@ void cpc_tty_init(pc300dev_t *pc300dev) cpc_tty->tty_minor = port + CPC_TTY_MINOR_START; cpc_tty->pc300dev = pc300dev; - INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty); - INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port); + INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work); + INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work); cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL; @@ -659,21 +659,23 @@ static void cpc_tty_hangup(struct tty_struct *tty) * o call the line disc. read * o free memory */ -static void cpc_tty_rx_work(void * data) +static void cpc_tty_rx_work(struct work_struct *work) { + st_cpc_tty_area *cpc_tty; unsigned long port; int i, j; - st_cpc_tty_area *cpc_tty; volatile st_cpc_rx_buf *buf; char flags=0,flg_rx=1; struct tty_ldisc *ld; if (cpc_tty_cnt == 0) return; - for (i=0; (i < 4) && flg_rx ; i++) { flg_rx = 0; - port = (unsigned long)data; + + cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work); + port = cpc_tty - cpc_tty_area; + for (j=0; j < CPC_TTY_NPORTS; j++) { cpc_tty = &cpc_tty_area[port]; @@ -882,9 +884,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) * o if need call line discipline wakeup * o call wake_up_interruptible */ -static void cpc_tty_tx_work(void *data) +static void cpc_tty_tx_work(struct work_struct *work) { - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; + st_cpc_tty_area *cpc_tty = + container_of(work, st_cpc_tty_area, tty_tx_work); struct tty_struct *tty; CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name); diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index fc75bec1902..fc5c0c611ff 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -119,7 +119,7 @@ static int sbni_ioctl( struct net_device *, struct ifreq *, int ); static struct net_device_stats *sbni_get_stats( struct net_device * ); static void set_multicast_list( struct net_device * ); -static irqreturn_t sbni_interrupt( int, void *, struct pt_regs * ); +static irqreturn_t sbni_interrupt( int, void * ); static void handle_channel( struct net_device * ); static int recv_frame( struct net_device * ); static void send_frame( struct net_device * ); @@ -501,7 +501,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) */ static irqreturn_t -sbni_interrupt( int irq, void *dev_id, struct pt_regs *regs ) +sbni_interrupt( int irq, void *dev_id ) { struct net_device *dev = (struct net_device *) dev_id; struct net_local *nl = (struct net_local *) dev->priv; diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 0ba018f8382..6a485f0556f 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -867,7 +867,7 @@ static void sdla_receive(struct net_device *dev) spin_unlock_irqrestore(&sdla_lock, flags); } -static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t sdla_isr(int irq, void *dev_id) { struct net_device *dev; struct frad_local *flp; @@ -875,13 +875,7 @@ static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs) dev = dev_id; - if (dev == NULL) - { - printk(KERN_WARNING "sdla_isr(): irq %d for unknown device.\n", irq); - return IRQ_NONE; - } - - flp = dev->priv; + flp = netdev_priv(dev); if (!flp->initialized) { diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index c13b459a013..218f7b574ab 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -469,7 +469,7 @@ static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) struct net_device *dev = sp->pp_if; int len = skb->len; u8 *p, opt[6]; - u32 rmagic; + u32 rmagic = 0; if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { if (sp->pp_flags & PP_DEBUG) @@ -763,7 +763,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) { struct in_device *in_dev; struct in_ifaddr *ifa; - u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ + __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ #ifdef CONFIG_INET rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index ec68f7dfd93..c7360157433 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -244,7 +244,7 @@ static inline void wanxl_rx_intr(card_t *card) -static irqreturn_t wanxl_intr(int irq, void* dev_id, struct pt_regs *regs) +static irqreturn_t wanxl_intr(int irq, void* dev_id) { card_t *card = dev_id; int i; diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index caa48f12fd0..59ddd21c395 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -728,7 +728,7 @@ EXPORT_SYMBOL(z8530_nop); * channel). c->lock for both channels points to dev->lock */ -irqreturn_t z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t z8530_interrupt(int irq, void *dev_id) { struct z8530_dev *dev=dev_id; u8 intr; diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h index 77e53208045..158aea7b8ea 100644 --- a/drivers/net/wan/z85230.h +++ b/drivers/net/wan/z85230.h @@ -396,7 +396,7 @@ struct z8530_dev extern u8 z8530_dead_port[]; extern u8 z8530_hdlc_kilostream_85230[]; extern u8 z8530_hdlc_kilostream[]; -extern irqreturn_t z8530_interrupt(int, void *, struct pt_regs *); +extern irqreturn_t z8530_interrupt(int, void *); extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io); extern int z8530_init(struct z8530_dev *); extern int z8530_shutdown(struct z8530_dev *); |