diff options
Diffstat (limited to 'drivers/net/wan')
52 files changed, 5565 insertions, 14579 deletions
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index a3df09ee729..94e234975c6 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -25,7 +25,7 @@ if WAN # There is no way to detect a comtrol sv11 - force it modular for now. config HOSTESS_SV11 tristate "Comtrol Hostess SV-11 support" - depends on ISA && m && ISA_DMA_API && INET + depends on ISA && m && ISA_DMA_API && INET && HDLC help Driver for Comtrol Hostess SV-11 network card which operates on low speed synchronous serial links at up to @@ -37,7 +37,7 @@ config HOSTESS_SV11 # The COSA/SRP driver has not been tested as non-modular yet. config COSA tristate "COSA/SRP sync serial boards support" - depends on ISA && m && ISA_DMA_API + depends on ISA && m && ISA_DMA_API && HDLC ---help--- Driver for COSA and SRP synchronous serial boards. @@ -61,7 +61,7 @@ config COSA # config LANMEDIA tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" - depends on PCI && VIRT_TO_BUS + depends on PCI && VIRT_TO_BUS && HDLC ---help--- Driver for the following Lan Media family of serial boards: @@ -78,9 +78,8 @@ config LANMEDIA - LMC 5245 board connects directly to a T3 circuit saving the additional external hardware. - To change setting such as syncPPP vs Cisco HDLC or clock source you - will need lmcctl. It is available at <ftp://ftp.lanmedia.com/> - (broken link). + To change setting such as clock source you will need lmcctl. + It is available at <ftp://ftp.lanmedia.com/> (broken link). To compile this driver as a module, choose M here: the module will be called lmc. @@ -88,7 +87,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 ISA && m && ISA_DMA_API && INET + depends on ISA && m && ISA_DMA_API && INET && HDLC help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. @@ -204,35 +203,6 @@ config WANXL_BUILD_FIRMWARE You should never need this option, say N. -config PC300 - tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" - depends on HDLC && PCI - ---help--- - Driver for the Cyclades-PC300 synchronous communication boards. - - These boards provide synchronous serial interfaces to your - Linux box (interfaces currently available are RS-232/V.35, X.21 and - T1/E1). If you wish to support Multilink PPP, please select the - option later and read the file README.mlppp provided by PC300 - package. - - To compile this as a module, choose M here: the module - will be called pc300. - - If unsure, say N. - -config PC300_MLPPP - bool "Cyclades-PC300 MLPPP support" - depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP - help - Multilink PPP over the PC300 synchronous communication boards. - -comment "Cyclades-PC300 MLPPP support is disabled." - depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) - -comment "Refer to the file README.mlppp, provided by PC300 package." - depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) - config PC300TOO tristate "Cyclades PC300 RSV/X21 alternative support" depends on HDLC && PCI @@ -289,8 +259,8 @@ config FARSYNC Frame Relay or X.25/LAPB. If you want the module to be automatically loaded when the interface - is referenced then you should add "alias hdlcX farsync" to - /etc/modprobe.conf for each interface, where X is 0, 1, 2, ..., or + is referenced then you should add "alias hdlcX farsync" to a file + in /etc/modprobe.d/ for each interface, where X is 0, 1, 2, ..., or simply use "alias hdlc* farsync" to indicate all of them. To compile this driver as a module, choose M here: the @@ -334,6 +304,13 @@ config DSCC4_PCI_RST Say Y if your card supports this feature. +config IXP4XX_HSS + tristate "Intel IXP4xx HSS (synchronous serial port) support" + depends on HDLC && ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR + help + Say Y here if you want to use built-in HSS ports + on IXP4xx processor. + config DLCI tristate "Frame Relay DLCI support" ---help--- @@ -379,64 +356,9 @@ config SDLA To compile this driver as a module, choose M here: the module will be called sdla. -# Wan router core. -config WAN_ROUTER_DRIVERS - tristate "WAN router drivers" - depends on WAN_ROUTER - ---help--- - Connect LAN to WAN via Linux box. - - Select driver your card and remember to say Y to "Wan Router." - You will need the wan-tools package which is available from - <ftp://ftp.sangoma.com/>. For more information read: - <file:Documentation/networking/wan-router.txt>. - - Note that the answer to this question won't directly affect the - 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. - -config CYCLADES_SYNC - tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)" - depends on WAN_ROUTER_DRIVERS && (PCI || ISA) - ---help--- - Cyclom 2X from Cyclades Corporation <http://www.cyclades.com/> is an - intelligent multiprotocol WAN adapter with data transfer rates up to - 512 Kbps. These cards support the X.25 and SNA related protocols. - - While no documentation is available at this time please grab the - wanconfig tarball in - <http://www.conectiva.com.br/~acme/cycsyn-devel/> (with minor changes - to make it compile with the current wanrouter include files; efforts - are being made to use the original package available at - <ftp://ftp.sangoma.com/>). - - Feel free to contact me or the cycsyn-devel mailing list at - <acme@conectiva.com.br> and <cycsyn-devel@bazar.conectiva.com.br> for - additional details, I hope to have documentation available as soon as - possible. (Cyclades Brazil is writing the Documentation). - - The next questions will ask you about the protocols you want the - driver to support (for now only X.25 is supported). - - If you have one or more of these cards, say Y to this option. - - To compile this driver as a module, choose M here: the - module will be called cyclomx. - -config CYCLOMX_X25 - bool "Cyclom 2X X.25 support (EXPERIMENTAL)" - depends on CYCLADES_SYNC - help - Connect a Cyclom 2X card to an X.25 network. - - Enabling X.25 support will enlarge your kernel by about 11 kB. - # X.25 network drivers config LAPBETHER - tristate "LAPB over Ethernet driver (EXPERIMENTAL)" + tristate "LAPB over Ethernet driver" depends on LAPB && X25 ---help--- Driver for a pseudo device (typically called /dev/lapb0) which allows @@ -452,8 +374,8 @@ config LAPBETHER If unsure, say N. config X25_ASY - tristate "X.25 async driver (EXPERIMENTAL)" - depends on LAPB && X25 + tristate "X.25 async driver" + depends on LAPB && X25 && TTY ---help--- Send and receive X.25 frames over regular asynchronous serial lines such as telephone lines equipped with ordinary modems. diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index d61fef36afc..c135ef47cbc 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -5,43 +5,33 @@ # Rewritten to use lists instead of if-statements. # -cyclomx-y := cycx_main.o -cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o -cyclomx-objs := $(cyclomx-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_PPP) += hdlc_ppp.o obj-$(CONFIG_HDLC_X25) += hdlc_x25.o -pc300-y := pc300_drv.o -pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o -pc300-objs := $(pc300-y) - -obj-$(CONFIG_HOSTESS_SV11) += z85230.o syncppp.o hostess_sv11.o -obj-$(CONFIG_SEALEVEL_4021) += z85230.o syncppp.o sealevel.o -obj-$(CONFIG_COSA) += syncppp.o cosa.o -obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o -obj-$(CONFIG_DSCC4) += dscc4.o -obj-$(CONFIG_LANMEDIA) += syncppp.o +obj-$(CONFIG_HOSTESS_SV11) += z85230.o hostess_sv11.o +obj-$(CONFIG_SEALEVEL_4021) += z85230.o sealevel.o +obj-$(CONFIG_COSA) += cosa.o +obj-$(CONFIG_FARSYNC) += farsync.o +obj-$(CONFIG_DSCC4) += dscc4.o obj-$(CONFIG_X25_ASY) += x25_asy.o obj-$(CONFIG_LANMEDIA) += lmc/ obj-$(CONFIG_DLCI) += dlci.o obj-$(CONFIG_SDLA) += sdla.o -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_N2) += n2.o obj-$(CONFIG_C101) += c101.o obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_PCI200SYN) += pci200syn.o obj-$(CONFIG_PC300TOO) += pc300too.o +obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o clean-files := wanxlfw.inc $(obj)/wanxl.o: $(obj)/wanxlfw.inc @@ -57,9 +47,9 @@ endif quiet_cmd_build_wanxlfw = BLD FW $@ cmd_build_wanxlfw = \ - $(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \ + $(CPP) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \ $(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \ - hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \ + hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static const u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \ rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o $(obj)/wanxlfw.inc: $(src)/wanxlfw.S diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index c4c8eab8574..09a50751763 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -14,8 +14,11 @@ * Moxa C101 User's Manual */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> +#include <linux/capability.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/string.h> @@ -88,7 +91,7 @@ static card_t **new_card = &first_card; /* EDA address register must be set in EDAL, EDAH order - 8 bit ISA bus */ #define sca_outw(value, reg, card) do { \ writeb(value & 0xFF, (card)->win0base + C101_SCA + (reg)); \ - writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg+1));\ + writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg + 1));\ } while(0) #define port_to_card(port) (port) @@ -113,7 +116,7 @@ static inline void openwin(card_t *card, u8 page) } -#include "hd6457x.c" +#include "hd64570.c" static inline void set_carrier(port_t *port) @@ -133,9 +136,9 @@ static void sca_msci_intr(port_t *port) sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port); if (stat & ST1_UDRN) { - struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); - stats->tx_errors++; /* TX Underrun error detected */ - stats->tx_fifo_errors++; + /* TX Underrun error detected */ + port_to_dev(port)->stats.tx_errors++; + port_to_dev(port)->stats.tx_fifo_errors++; } stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */ @@ -263,7 +266,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; @@ -296,7 +299,13 @@ static void c101_destroy_card(card_t *card) kfree(card); } - +static const struct net_device_ops c101_ops = { + .ndo_open = c101_open, + .ndo_stop = c101_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = c101_ioctl, +}; static int __init c101_run(unsigned long irq, unsigned long winbase) { @@ -306,44 +315,42 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) int result; if (irq<3 || irq>15 || irq == 6) /* FIXME */ { - printk(KERN_ERR "c101: invalid IRQ value\n"); + pr_err("invalid IRQ value\n"); return -ENODEV; } if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) { - printk(KERN_ERR "c101: invalid RAM value\n"); + pr_err("invalid RAM value\n"); return -ENODEV; } card = kzalloc(sizeof(card_t), GFP_KERNEL); - if (card == NULL) { - printk(KERN_ERR "c101: unable to allocate memory\n"); + if (card == NULL) return -ENOBUFS; - } card->dev = alloc_hdlcdev(card); if (!card->dev) { - printk(KERN_ERR "c101: unable to allocate memory\n"); + pr_err("unable to allocate memory\n"); kfree(card); return -ENOBUFS; } if (request_irq(irq, sca_intr, 0, devname, card)) { - printk(KERN_ERR "c101: could not allocate IRQ\n"); + pr_err("could not allocate IRQ\n"); c101_destroy_card(card); return -EBUSY; } card->irq = irq; if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) { - printk(KERN_ERR "c101: could not request RAM window\n"); + pr_err("could not request RAM window\n"); c101_destroy_card(card); return -EBUSY; } card->phy_winbase = winbase; card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE); if (!card->win0base) { - printk(KERN_ERR "c101: could not map I/O address\n"); + pr_err("could not map I/O address\n"); c101_destroy_card(card); return -EFAULT; } @@ -367,27 +374,23 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) dev->mem_start = winbase; dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1; dev->tx_queue_len = 50; - dev->do_ioctl = c101_ioctl; - dev->open = c101_open; - dev->stop = c101_close; + dev->netdev_ops = &c101_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; card->settings.clock_type = CLOCK_EXT; result = register_hdlc_device(dev); if (result) { - printk(KERN_WARNING "c101: unable to register hdlc device\n"); + pr_warn("unable to register hdlc device\n"); c101_destroy_card(card); return result; } - sca_init_sync_port(card); /* Set up C101 memory */ + sca_init_port(card); /* Set up C101 memory */ set_carrier(card); - printk(KERN_INFO "%s: Moxa C101 on IRQ%u," - " using %u TX + %u RX packets rings\n", - dev->name, card->irq, - card->tx_ring_buffers, card->rx_ring_buffers); + netdev_info(dev, "Moxa C101 on IRQ%u, using %u TX + %u RX packets rings\n", + card->irq, card->tx_ring_buffers, card->rx_ring_buffers); *new_card = card; new_card = &card->next_card; @@ -400,12 +403,12 @@ static int __init c101_init(void) { if (hw == NULL) { #ifdef MODULE - printk(KERN_INFO "c101: no card initialized\n"); + pr_info("no card initialized\n"); #endif - return -ENOSYS; /* no parameters specified, abort */ + return -EINVAL; /* no parameters specified, abort */ } - printk(KERN_INFO "%s\n", version); + pr_info("%s\n", version); do { unsigned long irq, ram; @@ -420,11 +423,11 @@ static int __init c101_init(void) c101_run(irq, ram); if (*hw == '\x0') - return first_card ? 0 : -ENOSYS; + return first_card ? 0 : -EINVAL; }while(*hw++ == ':'); - printk(KERN_ERR "c101: invalid hardware parameters\n"); - return first_card ? 0 : -ENOSYS; + pr_err("invalid hardware parameters\n"); + return first_card ? 0 : -EINVAL; } diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 1d706eae305..83c39e2858b 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -2,6 +2,7 @@ /* * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz> + * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +55,7 @@ * * The Linux driver (unlike the present *BSD drivers :-) can work even * for the COSA and SRP in one computer and allows each channel to work - * in one of the three modes (character device, Cisco HDLC, Sync PPP). + * in one of the two modes (character or network device). * * AUTHOR * @@ -72,33 +73,30 @@ * The Comtrol Hostess SV11 driver by Alan Cox * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox */ -/* - * 5/25/1999 : Marcelo Tosatti <marcelo@conectiva.com.br> - * fixed a deadlock in cosa_sppp_open - */ - -/* ---------- Headers, macros, data structures ---------- */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> #include <linux/kernel.h> +#include <linux/sched.h> #include <linux/slab.h> #include <linux/poll.h> #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/hdlc.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/netdevice.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/device.h> - -#undef COSA_SLOW_IO /* for testing purposes only */ - #include <asm/io.h> #include <asm/dma.h> #include <asm/byteorder.h> -#include <net/syncppp.h> +#undef COSA_SLOW_IO /* for testing purposes only */ + #include "cosa.h" /* Maximum length of the identification string. */ @@ -110,7 +108,6 @@ /* Per-channel data structure */ struct channel_data { - void *if_ptr; /* General purpose pointer (used by SPPP) */ int usage; /* Usage count; >0 for chrdev, -1 for netdev */ int num; /* Number of the channel */ struct cosa_data *cosa; /* Pointer to the per-card structure */ @@ -127,16 +124,16 @@ struct channel_data { int (*tx_done)(struct channel_data *channel, int size); /* Character device parts */ - struct semaphore rsem, wsem; + struct mutex rlock; + struct semaphore wsem; char *rxdata; int rxsize; wait_queue_head_t txwaitq, rxwaitq; int tx_status, rx_status; - /* SPPP/HDLC device parts */ - struct ppp_device pppdev; + /* generic HDLC device parts */ + struct net_device *netdev; struct sk_buff *rx_skb, *tx_skb; - struct net_device_stats stats; }; /* cosa->firmware_status bits */ @@ -178,6 +175,7 @@ struct cosa_data { * Character device major number. 117 was allocated for us. * The value of 0 means to allocate a first free one. */ +static DEFINE_MUTEX(cosa_chardev_mutex); static int cosa_major = 117; /* @@ -278,21 +276,19 @@ static int cosa_start_tx(struct channel_data *channel, char *buf, int size); static void cosa_kick(struct cosa_data *cosa); static int cosa_dma_able(struct channel_data *chan, char *buf, int data); -/* SPPP/HDLC stuff */ -static void sppp_channel_init(struct channel_data *chan); -static void sppp_channel_delete(struct channel_data *chan); -static int cosa_sppp_open(struct net_device *d); -static int cosa_sppp_close(struct net_device *d); -static void cosa_sppp_timeout(struct net_device *d); -static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *d); -static char *sppp_setup_rx(struct channel_data *channel, int size); -static int sppp_rx_done(struct channel_data *channel); -static int sppp_tx_done(struct channel_data *channel, int size); -static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static struct net_device_stats *cosa_net_stats(struct net_device *dev); +/* Network device stuff */ +static int cosa_net_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity); +static int cosa_net_open(struct net_device *d); +static int cosa_net_close(struct net_device *d); +static void cosa_net_timeout(struct net_device *d); +static netdev_tx_t cosa_net_tx(struct sk_buff *skb, struct net_device *d); +static char *cosa_net_setup_rx(struct channel_data *channel, int size); +static int cosa_net_rx_done(struct channel_data *channel); +static int cosa_net_tx_done(struct channel_data *channel, int size); +static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); /* Character device */ -static void chardev_channel_init(struct channel_data *chan); static char *chrdev_setup_rx(struct channel_data *channel, int size); static int chrdev_rx_done(struct channel_data *channel); static int chrdev_tx_done(struct channel_data *channel, int size); @@ -303,8 +299,8 @@ static ssize_t cosa_write(struct file *file, static unsigned int cosa_poll(struct file *file, poll_table *poll); static int cosa_open(struct inode *inode, struct file *file); static int cosa_release(struct inode *inode, struct file *file); -static int cosa_chardev_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long cosa_chardev_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); #ifdef COSA_FASYNC_WORKING static int cosa_fasync(struct inode *inode, struct file *file, int on); #endif @@ -315,7 +311,7 @@ static const struct file_operations cosa_fops = { .read = cosa_read, .write = cosa_write, .poll = cosa_poll, - .ioctl = cosa_chardev_ioctl, + .unlocked_ioctl = cosa_chardev_ioctl, .open = cosa_open, .release = cosa_release, #ifdef COSA_FASYNC_WORKING @@ -335,7 +331,7 @@ static int startmicrocode(struct cosa_data *cosa, int address); static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len); static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id); -/* Auxilliary functions */ +/* Auxiliary functions */ static int get_wait_data(struct cosa_data *cosa); static int put_wait_data(struct cosa_data *cosa, int data); static int puthexnumber(struct cosa_data *cosa, int number); @@ -354,27 +350,26 @@ static void debug_status_in(struct cosa_data *cosa, int status); static void debug_status_out(struct cosa_data *cosa, int status); #endif - +static inline struct channel_data* dev_to_chan(struct net_device *dev) +{ + return (struct channel_data *)dev_to_hdlc(dev)->priv; +} + /* ---------- Initialization stuff ---------- */ static int __init cosa_init(void) { int i, err = 0; - printk(KERN_INFO "cosa v1.08 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>\n"); -#ifdef CONFIG_SMP - printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n"); -#endif if (cosa_major > 0) { if (register_chrdev(cosa_major, "cosa", &cosa_fops)) { - printk(KERN_WARNING "cosa: unable to get major %d\n", - cosa_major); + pr_warn("unable to get major %d\n", cosa_major); err = -EIO; goto out; } } else { if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) { - printk(KERN_WARNING "cosa: unable to register chardev\n"); + pr_warn("unable to register chardev\n"); err = -EIO; goto out; } @@ -384,7 +379,7 @@ static int __init cosa_init(void) for (i=0; io[i] != 0 && i < MAX_CARDS; i++) cosa_probe(io[i], irq[i], dma[i]); if (!nr_cards) { - printk(KERN_WARNING "cosa: no devices found.\n"); + pr_warn("no devices found\n"); unregister_chrdev(cosa_major, "cosa"); err = -ENODEV; goto out; @@ -394,12 +389,12 @@ static int __init cosa_init(void) err = PTR_ERR(cosa_class); goto out_chrdev; } - for (i=0; i<nr_cards; i++) { - device_create(cosa_class, NULL, MKDEV(cosa_major, i), "cosa%d", i); - } + for (i = 0; i < nr_cards; i++) + device_create(cosa_class, NULL, MKDEV(cosa_major, i), NULL, + "cosa%d", i); err = 0; goto out; - + out_chrdev: unregister_chrdev(cosa_major, "cosa"); out: @@ -411,43 +406,38 @@ static void __exit cosa_exit(void) { struct cosa_data *cosa; int i; - printk(KERN_INFO "Unloading the cosa module\n"); - for (i=0; i<nr_cards; i++) + for (i = 0; i < nr_cards; i++) device_destroy(cosa_class, MKDEV(cosa_major, i)); class_destroy(cosa_class); - for (cosa=cosa_cards; nr_cards--; cosa++) { + + for (cosa = cosa_cards; nr_cards--; cosa++) { /* Clean up the per-channel data */ - for (i=0; i<cosa->nchannels; i++) { + for (i = 0; i < cosa->nchannels; i++) { /* Chardev driver has no alloc'd per-channel data */ - sppp_channel_delete(cosa->chan+i); + unregister_hdlc_device(cosa->chan[i].netdev); + free_netdev(cosa->chan[i].netdev); } /* Clean up the per-card data */ kfree(cosa->chan); kfree(cosa->bouncebuf); free_irq(cosa->irq, cosa); free_dma(cosa->dma); - release_region(cosa->datareg,is_8bit(cosa)?2:4); + release_region(cosa->datareg, is_8bit(cosa) ? 2 : 4); } unregister_chrdev(cosa_major, "cosa"); } module_exit(cosa_exit); -/* - * This function should register all the net devices needed for the - * single channel. - */ -static __inline__ void channel_init(struct channel_data *chan) -{ - sprintf(chan->name, "cosa%dc%d", chan->cosa->num, chan->num); - - /* Initialize the chardev data structures */ - chardev_channel_init(chan); +static const struct net_device_ops cosa_ops = { + .ndo_open = cosa_net_open, + .ndo_stop = cosa_net_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = cosa_net_ioctl, + .ndo_tx_timeout = cosa_net_timeout, +}; - /* Register the sppp interface */ - sppp_channel_init(chan); -} - static int cosa_probe(int base, int irq, int dma) { struct cosa_data *cosa = cosa_cards+nr_cards; @@ -458,26 +448,25 @@ static int cosa_probe(int base, int irq, int dma) /* Checking validity of parameters: */ /* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */ if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) { - printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq); + pr_info("invalid IRQ %d\n", irq); return -1; } /* I/O address should be between 0x100 and 0x3ff and should be * multiple of 8. */ if (base < 0x100 || base > 0x3ff || base & 0x7) { - printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n", - base); + pr_info("invalid I/O address 0x%x\n", base); return -1; } /* DMA should be 0,1 or 3-7 */ if (dma < 0 || dma == 4 || dma > 7) { - printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma); + pr_info("invalid DMA %d\n", dma); return -1; } /* and finally, on 16-bit COSA DMA should be 4-7 and * I/O base should not be multiple of 0x10 */ if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) { - printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch" - " (base=0x%x, dma=%d)\n", base, dma); + pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n", + base, dma); return -1; } @@ -490,7 +479,7 @@ static int cosa_probe(int base, int irq, int dma) return -1; if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) { - printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base); + printk(KERN_DEBUG "probe at 0x%x failed.\n", base); err = -1; goto err_out; } @@ -503,8 +492,7 @@ static int cosa_probe(int base, int irq, int dma) else { /* Print a warning only if we are not autoprobing */ #ifndef COSA_ISA_AUTOPROBE - printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n", - base); + pr_info("valid signature not found at 0x%x\n", base); #endif err = -1; goto err_out; @@ -512,14 +500,14 @@ static int cosa_probe(int base, int irq, int dma) /* Update the name of the region now we know the type of card */ release_region(base, is_8bit(cosa)?2:4); if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) { - printk(KERN_DEBUG "cosa: changing name at 0x%x failed.\n", base); + printk(KERN_DEBUG "changing name at 0x%x failed.\n", base); return -1; } /* Now do IRQ autoprobe */ if (irq < 0) { unsigned long irqs; -/* printk(KERN_INFO "IRQ autoprobe\n"); */ +/* pr_info("IRQ autoprobe\n"); */ irqs = probe_irq_on(); /* * Enable interrupt on tx buffer empty (it sure is) @@ -537,13 +525,13 @@ static int cosa_probe(int base, int irq, int dma) cosa_getdata8(cosa); if (irq < 0) { - printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n", + pr_info("multiple interrupts obtained (%d, board at 0x%x)\n", irq, cosa->datareg); err = -1; goto err_out; } if (irq == 0) { - printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n", + pr_info("no interrupt obtained (board at 0x%x)\n", cosa->datareg); /* return -1; */ } @@ -573,140 +561,137 @@ static int cosa_probe(int base, int irq, int dma) /* Initialize the per-channel data */ cosa->chan = kcalloc(cosa->nchannels, sizeof(struct channel_data), GFP_KERNEL); if (!cosa->chan) { - err = -ENOMEM; + err = -ENOMEM; goto err_out3; } - for (i=0; i<cosa->nchannels; i++) { - cosa->chan[i].cosa = cosa; - cosa->chan[i].num = i; - channel_init(cosa->chan+i); + + for (i = 0; i < cosa->nchannels; i++) { + struct channel_data *chan = &cosa->chan[i]; + + chan->cosa = cosa; + chan->num = i; + sprintf(chan->name, "cosa%dc%d", chan->cosa->num, i); + + /* Initialize the chardev data structures */ + mutex_init(&chan->rlock); + sema_init(&chan->wsem, 1); + + /* Register the network interface */ + if (!(chan->netdev = alloc_hdlcdev(chan))) { + pr_warn("%s: alloc_hdlcdev failed\n", chan->name); + goto err_hdlcdev; + } + dev_to_hdlc(chan->netdev)->attach = cosa_net_attach; + dev_to_hdlc(chan->netdev)->xmit = cosa_net_tx; + chan->netdev->netdev_ops = &cosa_ops; + chan->netdev->watchdog_timeo = TX_TIMEOUT; + chan->netdev->base_addr = chan->cosa->datareg; + chan->netdev->irq = chan->cosa->irq; + chan->netdev->dma = chan->cosa->dma; + if (register_hdlc_device(chan->netdev)) { + netdev_warn(chan->netdev, + "register_hdlc_device() failed\n"); + free_netdev(chan->netdev); + goto err_hdlcdev; + } } - printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n", + pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n", cosa->num, cosa->id_string, cosa->type, cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels); return nr_cards++; + +err_hdlcdev: + while (i-- > 0) { + unregister_hdlc_device(cosa->chan[i].netdev); + free_netdev(cosa->chan[i].netdev); + } + kfree(cosa->chan); err_out3: kfree(cosa->bouncebuf); err_out2: free_dma(cosa->dma); err_out1: free_irq(cosa->irq, cosa); -err_out: +err_out: release_region(cosa->datareg,is_8bit(cosa)?2:4); - printk(KERN_NOTICE "cosa%d: allocating resources failed\n", - cosa->num); + pr_notice("cosa%d: allocating resources failed\n", cosa->num); return err; } -/*---------- SPPP/HDLC netdevice ---------- */ - -static void cosa_setup(struct net_device *d) -{ - d->open = cosa_sppp_open; - d->stop = cosa_sppp_close; - d->hard_start_xmit = cosa_sppp_tx; - d->do_ioctl = cosa_sppp_ioctl; - d->get_stats = cosa_net_stats; - d->tx_timeout = cosa_sppp_timeout; - d->watchdog_timeo = TX_TIMEOUT; -} +/*---------- network device ---------- */ -static void sppp_channel_init(struct channel_data *chan) +static int cosa_net_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - struct net_device *d; - chan->if_ptr = &chan->pppdev; - d = alloc_netdev(0, chan->name, cosa_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", chan->name); - return; - } - chan->pppdev.dev = d; - d->base_addr = chan->cosa->datareg; - d->irq = chan->cosa->irq; - d->dma = chan->cosa->dma; - d->priv = chan; - sppp_attach(&chan->pppdev); - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(d); - free_netdev(d); - chan->pppdev.dev = NULL; - return; - } -} - -static void sppp_channel_delete(struct channel_data *chan) -{ - unregister_netdev(chan->pppdev.dev); - sppp_detach(chan->pppdev.dev); - free_netdev(chan->pppdev.dev); - chan->pppdev.dev = NULL; + if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT) + return 0; + return -EINVAL; } -static int cosa_sppp_open(struct net_device *d) +static int cosa_net_open(struct net_device *dev) { - struct channel_data *chan = d->priv; + struct channel_data *chan = dev_to_chan(dev); int err; unsigned long flags; if (!(chan->cosa->firmware_status & COSA_FW_START)) { - printk(KERN_NOTICE "%s: start the firmware first (status %d)\n", - chan->cosa->name, chan->cosa->firmware_status); + pr_notice("%s: start the firmware first (status %d)\n", + chan->cosa->name, chan->cosa->firmware_status); return -EPERM; } spin_lock_irqsave(&chan->cosa->lock, flags); if (chan->usage != 0) { - printk(KERN_WARNING "%s: sppp_open called with usage count %d\n", + pr_warn("%s: cosa_net_open called with usage count %d\n", chan->name, chan->usage); spin_unlock_irqrestore(&chan->cosa->lock, flags); return -EBUSY; } - chan->setup_rx = sppp_setup_rx; - chan->tx_done = sppp_tx_done; - chan->rx_done = sppp_rx_done; - chan->usage=-1; + chan->setup_rx = cosa_net_setup_rx; + chan->tx_done = cosa_net_tx_done; + chan->rx_done = cosa_net_rx_done; + chan->usage = -1; chan->cosa->usage++; spin_unlock_irqrestore(&chan->cosa->lock, flags); - err = sppp_open(d); + err = hdlc_open(dev); if (err) { spin_lock_irqsave(&chan->cosa->lock, flags); - chan->usage=0; + chan->usage = 0; chan->cosa->usage--; - spin_unlock_irqrestore(&chan->cosa->lock, flags); return err; } - netif_start_queue(d); + netif_start_queue(dev); cosa_enable_rx(chan); return 0; } -static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t cosa_net_tx(struct sk_buff *skb, + struct net_device *dev) { - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev_to_chan(dev); netif_stop_queue(dev); chan->tx_skb = skb; cosa_start_tx(chan, skb->data, skb->len); - return 0; + return NETDEV_TX_OK; } -static void cosa_sppp_timeout(struct net_device *dev) +static void cosa_net_timeout(struct net_device *dev) { - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev_to_chan(dev); if (test_bit(RXBIT, &chan->cosa->rxtx)) { - chan->stats.rx_errors++; - chan->stats.rx_missed_errors++; + chan->netdev->stats.rx_errors++; + chan->netdev->stats.rx_missed_errors++; } else { - chan->stats.tx_errors++; - chan->stats.tx_aborted_errors++; + chan->netdev->stats.tx_errors++; + chan->netdev->stats.tx_aborted_errors++; } cosa_kick(chan->cosa); if (chan->tx_skb) { @@ -716,13 +701,13 @@ static void cosa_sppp_timeout(struct net_device *dev) netif_wake_queue(dev); } -static int cosa_sppp_close(struct net_device *d) +static int cosa_net_close(struct net_device *dev) { - struct channel_data *chan = d->priv; + struct channel_data *chan = dev_to_chan(dev); unsigned long flags; - netif_stop_queue(d); - sppp_close(d); + netif_stop_queue(dev); + hdlc_close(dev); cosa_disable_rx(chan); spin_lock_irqsave(&chan->cosa->lock, flags); if (chan->rx_skb) { @@ -733,84 +718,66 @@ static int cosa_sppp_close(struct net_device *d) kfree_skb(chan->tx_skb); chan->tx_skb = NULL; } - chan->usage=0; + chan->usage = 0; chan->cosa->usage--; spin_unlock_irqrestore(&chan->cosa->lock, flags); return 0; } -static char *sppp_setup_rx(struct channel_data *chan, int size) +static char *cosa_net_setup_rx(struct channel_data *chan, int size) { /* * We can safely fall back to non-dma-able memory, because we have * the cosa->bouncebuf pre-allocated. */ - if (chan->rx_skb) - kfree_skb(chan->rx_skb); + kfree_skb(chan->rx_skb); chan->rx_skb = dev_alloc_skb(size); if (chan->rx_skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n", - chan->name); - chan->stats.rx_dropped++; + pr_notice("%s: Memory squeeze, dropping packet\n", chan->name); + chan->netdev->stats.rx_dropped++; return NULL; } - chan->pppdev.dev->trans_start = jiffies; + chan->netdev->trans_start = jiffies; return skb_put(chan->rx_skb, size); } -static int sppp_rx_done(struct channel_data *chan) +static int cosa_net_rx_done(struct channel_data *chan) { if (!chan->rx_skb) { - printk(KERN_WARNING "%s: rx_done with empty skb!\n", - chan->name); - chan->stats.rx_errors++; - chan->stats.rx_frame_errors++; + pr_warn("%s: rx_done with empty skb!\n", chan->name); + chan->netdev->stats.rx_errors++; + chan->netdev->stats.rx_frame_errors++; return 0; } - chan->rx_skb->protocol = htons(ETH_P_WAN_PPP); - chan->rx_skb->dev = chan->pppdev.dev; + chan->rx_skb->protocol = hdlc_type_trans(chan->rx_skb, chan->netdev); + chan->rx_skb->dev = chan->netdev; skb_reset_mac_header(chan->rx_skb); - chan->stats.rx_packets++; - chan->stats.rx_bytes += chan->cosa->rxsize; + chan->netdev->stats.rx_packets++; + chan->netdev->stats.rx_bytes += chan->cosa->rxsize; netif_rx(chan->rx_skb); chan->rx_skb = NULL; - chan->pppdev.dev->last_rx = jiffies; return 0; } /* ARGSUSED */ -static int sppp_tx_done(struct channel_data *chan, int size) +static int cosa_net_tx_done(struct channel_data *chan, int size) { if (!chan->tx_skb) { - printk(KERN_WARNING "%s: tx_done with empty skb!\n", - chan->name); - chan->stats.tx_errors++; - chan->stats.tx_aborted_errors++; + pr_warn("%s: tx_done with empty skb!\n", chan->name); + chan->netdev->stats.tx_errors++; + chan->netdev->stats.tx_aborted_errors++; return 1; } dev_kfree_skb_irq(chan->tx_skb); chan->tx_skb = NULL; - chan->stats.tx_packets++; - chan->stats.tx_bytes += size; - netif_wake_queue(chan->pppdev.dev); + chan->netdev->stats.tx_packets++; + chan->netdev->stats.tx_bytes += size; + netif_wake_queue(chan->netdev); return 1; } -static struct net_device_stats *cosa_net_stats(struct net_device *dev) -{ - struct channel_data *chan = dev->priv; - return &chan->stats; -} - - /*---------- Character device ---------- */ -static void chardev_channel_init(struct channel_data *chan) -{ - init_MUTEX(&chan->rsem); - init_MUTEX(&chan->wsem); -} - static ssize_t cosa_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -821,16 +788,16 @@ static ssize_t cosa_read(struct file *file, char *kbuf; if (!(cosa->firmware_status & COSA_FW_START)) { - printk(KERN_NOTICE "%s: start the firmware first (status %d)\n", - cosa->name, cosa->firmware_status); + pr_notice("%s: start the firmware first (status %d)\n", + cosa->name, cosa->firmware_status); return -EPERM; } - if (down_interruptible(&chan->rsem)) + if (mutex_lock_interruptible(&chan->rlock)) return -ERESTARTSYS; - if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) { - printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name); - up(&chan->rsem); + chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL); + if (chan->rxdata == NULL) { + mutex_unlock(&chan->rlock); return -ENOMEM; } @@ -838,7 +805,7 @@ static ssize_t cosa_read(struct file *file, cosa_enable_rx(chan); spin_lock_irqsave(&cosa->lock, flags); add_wait_queue(&chan->rxwaitq, &wait); - while(!chan->rx_status) { + while (!chan->rx_status) { current->state = TASK_INTERRUPTIBLE; spin_unlock_irqrestore(&cosa->lock, flags); schedule(); @@ -848,7 +815,7 @@ static ssize_t cosa_read(struct file *file, remove_wait_queue(&chan->rxwaitq, &wait); current->state = TASK_RUNNING; spin_unlock_irqrestore(&cosa->lock, flags); - up(&chan->rsem); + mutex_unlock(&chan->rlock); return -ERESTARTSYS; } } @@ -857,7 +824,7 @@ static ssize_t cosa_read(struct file *file, kbuf = chan->rxdata; count = chan->rxsize; spin_unlock_irqrestore(&cosa->lock, flags); - up(&chan->rsem); + mutex_unlock(&chan->rlock); if (copy_to_user(buf, kbuf, count)) { kfree(kbuf); @@ -896,8 +863,8 @@ static ssize_t cosa_write(struct file *file, char *kbuf; if (!(cosa->firmware_status & COSA_FW_START)) { - printk(KERN_NOTICE "%s: start the firmware first (status %d)\n", - cosa->name, cosa->firmware_status); + pr_notice("%s: start the firmware first (status %d)\n", + cosa->name, cosa->firmware_status); return -EPERM; } if (down_interruptible(&chan->wsem)) @@ -907,9 +874,8 @@ static ssize_t cosa_write(struct file *file, count = COSA_MTU; /* Allocate the buffer */ - if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) { - printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n", - cosa->name); + kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA); + if (kbuf == NULL) { up(&chan->wsem); return -ENOMEM; } @@ -923,7 +889,7 @@ static ssize_t cosa_write(struct file *file, spin_lock_irqsave(&cosa->lock, flags); add_wait_queue(&chan->txwaitq, &wait); - while(!chan->tx_status) { + while (!chan->tx_status) { current->state = TASK_INTERRUPTIBLE; spin_unlock_irqrestore(&cosa->lock, flags); schedule(); @@ -934,6 +900,7 @@ static ssize_t cosa_write(struct file *file, current->state = TASK_RUNNING; chan->tx_status = 1; spin_unlock_irqrestore(&cosa->lock, flags); + up(&chan->wsem); return -ERESTARTSYS; } } @@ -958,7 +925,7 @@ static int chrdev_tx_done(struct channel_data *chan, int size) static unsigned int cosa_poll(struct file *file, poll_table *poll) { - printk(KERN_INFO "cosa_poll is here\n"); + pr_info("cosa_poll is here\n"); return 0; } @@ -968,15 +935,21 @@ static int cosa_open(struct inode *inode, struct file *file) struct channel_data *chan; unsigned long flags; int n; + int ret = 0; - if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS) - >= nr_cards) - return -ENODEV; + mutex_lock(&cosa_chardev_mutex); + if ((n=iminor(file_inode(file))>>CARD_MINOR_BITS) + >= nr_cards) { + ret = -ENODEV; + goto out; + } cosa = cosa_cards+n; - if ((n=iminor(file->f_path.dentry->d_inode) - & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) - return -ENODEV; + if ((n=iminor(file_inode(file)) + & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) { + ret = -ENODEV; + goto out; + } chan = cosa->chan + n; file->private_data = chan; @@ -985,7 +958,8 @@ static int cosa_open(struct inode *inode, struct file *file) if (chan->usage < 0) { /* in netdev mode */ spin_unlock_irqrestore(&cosa->lock, flags); - return -EBUSY; + ret = -EBUSY; + goto out; } cosa->usage++; chan->usage++; @@ -994,7 +968,9 @@ static int cosa_open(struct inode *inode, struct file *file) chan->setup_rx = chrdev_setup_rx; chan->rx_done = chrdev_rx_done; spin_unlock_irqrestore(&cosa->lock, flags); - return 0; +out: + mutex_unlock(&cosa_chardev_mutex); + return ret; } static int cosa_release(struct inode *inode, struct file *file) @@ -1018,8 +994,8 @@ static struct fasync_struct *fasync[256] = { NULL, }; static int cosa_fasync(struct inode *inode, struct file *file, int on) { int port = iminor(inode); - int rv = fasync_helper(inode, file, on, &fasync[port]); - return rv < 0 ? rv : 0; + + return fasync_helper(inode, file, on, &fasync[port]); } #endif @@ -1034,15 +1010,14 @@ static inline int cosa_reset(struct cosa_data *cosa) { char idstring[COSA_MAX_ID_STRING]; if (cosa->usage > 1) - printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n", + pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->num, cosa->usage); cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START); if (cosa_reset_and_read_id(cosa, idstring) < 0) { - printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num); + pr_notice("cosa%d: reset failed\n", cosa->num); return -EIO; } - printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num, - idstring); + pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring); cosa->firmware_status |= COSA_FW_RESET; return 0; } @@ -1054,11 +1029,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg) int i; if (cosa->usage > 1) - printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", + pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->name, cosa->usage); if (!(cosa->firmware_status & COSA_FW_RESET)) { - printk(KERN_NOTICE "%s: reset the card first (status %d).\n", - cosa->name, cosa->firmware_status); + pr_notice("%s: reset the card first (status %d)\n", + cosa->name, cosa->firmware_status); return -EPERM; } @@ -1076,11 +1051,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg) i = download(cosa, d.code, d.len, d.addr); if (i < 0) { - printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n", - cosa->num, i); + pr_notice("cosa%d: microcode download failed: %d\n", + cosa->num, i); return -EIO; } - printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n", + pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n", cosa->num, d.len, d.addr); cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD; return 0; @@ -1093,12 +1068,11 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg) int i; if (cosa->usage > 1) - printk(KERN_INFO "cosa%d: WARNING: readmem requested with " - "cosa->usage > 1 (%d). Odd things may happen.\n", + pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->num, cosa->usage); if (!(cosa->firmware_status & COSA_FW_RESET)) { - printk(KERN_NOTICE "%s: reset the card first (status %d).\n", - cosa->name, cosa->firmware_status); + pr_notice("%s: reset the card first (status %d)\n", + cosa->name, cosa->firmware_status); return -EPERM; } @@ -1110,11 +1084,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg) i = readmem(cosa, d.code, d.len, d.addr); if (i < 0) { - printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n", - cosa->num, i); + pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i); return -EIO; } - printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n", + pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n", cosa->num, d.len, d.addr); cosa->firmware_status |= COSA_FW_RESET; return 0; @@ -1126,23 +1099,22 @@ static inline int cosa_start(struct cosa_data *cosa, int address) int i; if (cosa->usage > 1) - printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", + pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->num, cosa->usage); if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD)) != (COSA_FW_RESET|COSA_FW_DOWNLOAD)) { - printk(KERN_NOTICE "%s: download the microcode and/or reset the card first (status %d).\n", - cosa->name, cosa->firmware_status); + pr_notice("%s: download the microcode and/or reset the card first (status %d)\n", + cosa->name, cosa->firmware_status); return -EPERM; } cosa->firmware_status &= ~COSA_FW_RESET; if ((i=startmicrocode(cosa, address)) < 0) { - printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n", - cosa->num, address, i); + pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n", + cosa->num, address, i); return -EIO; } - printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n", - cosa->num, address); + pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address); cosa->startaddr = address; cosa->firmware_status |= COSA_FW_START; return 0; @@ -1170,7 +1142,7 @@ static int cosa_ioctl_common(struct cosa_data *cosa, struct channel_data *channel, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - switch(cmd) { + switch (cmd) { case COSAIORSET: /* Reset the device */ if (!capable(CAP_NET_ADMIN)) return -EACCES; @@ -1211,24 +1183,29 @@ static int cosa_ioctl_common(struct cosa_data *cosa, return -ENOIOCTLCMD; } -static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, - int cmd) +static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int rv; - struct channel_data *chan = dev->priv; - rv = cosa_ioctl_common(chan->cosa, chan, cmd, (unsigned long)ifr->ifr_data); - if (rv == -ENOIOCTLCMD) { - return sppp_do_ioctl(dev, ifr, cmd); - } - return rv; + struct channel_data *chan = dev_to_chan(dev); + rv = cosa_ioctl_common(chan->cosa, chan, cmd, + (unsigned long)ifr->ifr_data); + if (rv != -ENOIOCTLCMD) + return rv; + return hdlc_ioctl(dev, ifr, cmd); } -static int cosa_chardev_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long cosa_chardev_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct channel_data *channel = file->private_data; - struct cosa_data *cosa = channel->cosa; - return cosa_ioctl_common(cosa, channel, cmd, arg); + struct cosa_data *cosa; + long ret; + + mutex_lock(&cosa_chardev_mutex); + cosa = channel->cosa; + ret = cosa_ioctl_common(cosa, channel, cmd, arg); + mutex_unlock(&cosa_chardev_mutex); + return ret; } @@ -1267,11 +1244,11 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len) #ifdef DEBUG_DATA int i; - printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num, - chan->num, len); + pr_info("cosa%dc%d: starting tx(0x%x)", + chan->cosa->num, chan->num, len); for (i=0; i<len; i++) - printk(" %02x", buf[i]&0xff); - printk("\n"); + pr_cont(" %02x", buf[i]&0xff); + pr_cont("\n"); #endif spin_lock_irqsave(&cosa->lock, flags); chan->txbuf = buf; @@ -1365,7 +1342,7 @@ static void cosa_kick(struct cosa_data *cosa) if (test_bit(TXBIT, &cosa->rxtx)) s = "TX DMA"; - printk(KERN_INFO "%s: %s timeout - restarting.\n", cosa->name, s); + pr_info("%s: %s timeout - restarting\n", cosa->name, s); spin_lock_irqsave(&cosa->lock, flags); cosa->rxtx = 0; @@ -1399,7 +1376,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len) return 0; if ((b^ (b+len)) & 0x10000) { if (count++ < 5) - printk(KERN_INFO "%s: packet spanning a 64k boundary\n", + pr_info("%s: packet spanning a 64k boundary\n", chan->name); return 0; } @@ -1510,8 +1487,7 @@ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, i char c; int i; if ((i=get_wait_data(cosa)) == -1) { - printk (KERN_INFO "cosa: 0x%04x bytes remaining\n", - length); + pr_info("0x%04x bytes remaining\n", length); return -11; } c=i; @@ -1545,11 +1521,7 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring) cosa_putstatus(cosa, 0); cosa_getdata8(cosa); cosa_putstatus(cosa, SR_RST); -#ifdef MODULE msleep(500); -#else - udelay(5*100000); -#endif /* Disable all IRQs from the card */ cosa_putstatus(cosa, 0); @@ -1594,14 +1566,15 @@ static int get_wait_data(struct cosa_data *cosa) short r; r = cosa_getdata8(cosa); #if 0 - printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries); + pr_info("get_wait_data returning after %d retries\n", + 999-retries); #endif return r; } /* sleep if not ready to read */ schedule_timeout_interruptible(1); } - printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n", + pr_info("timeout in get_wait_data (status 0x%x)\n", cosa_getstatus(cosa)); return -1; } @@ -1619,7 +1592,7 @@ static int put_wait_data(struct cosa_data *cosa, int data) if (cosa_getstatus(cosa) & SR_TX_RDY) { cosa_putdata8(cosa, data); #if 0 - printk(KERN_INFO "Putdata: %d retries\n", 999-retries); + pr_info("Putdata: %d retries\n", 999-retries); #endif return 0; } @@ -1628,7 +1601,7 @@ static int put_wait_data(struct cosa_data *cosa, int data) schedule_timeout_interruptible(1); #endif } - printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n", + pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n", cosa->num, cosa_getstatus(cosa)); return -1; } @@ -1648,13 +1621,13 @@ static int puthexnumber(struct cosa_data *cosa, int number) sprintf(temp, "%04X", number); for (i=0; i<4; i++) { if (put_wait_data(cosa, temp[i]) == -1) { - printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n", - cosa->num, i); + pr_notice("cosa%d: puthexnumber failed to write byte %d\n", + cosa->num, i); return -1-2*i; } if (get_wait_data(cosa) != temp[i]) { - printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n", - cosa->num, i); + pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n", + cosa->num, i); return -2-2*i; } } @@ -1699,8 +1672,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) { unsigned long flags, flags1; #ifdef DEBUG_IRQS - printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n", - cosa->num, status); + pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status); #endif spin_lock_irqsave(&cosa->lock, flags); set_bit(TXBIT, &cosa->rxtx); @@ -1708,15 +1680,14 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) /* flow control, see the comment above */ int i=0; if (!cosa->txbitmap) { - printk(KERN_WARNING "%s: No channel wants data " - "in TX IRQ. Expect DMA timeout.", + pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n", cosa->name); put_driver_status_nolock(cosa); clear_bit(TXBIT, &cosa->rxtx); spin_unlock_irqrestore(&cosa->lock, flags); return; } - while(1) { + while (1) { cosa->txchan++; i++; if (cosa->txchan >= cosa->nchannels) @@ -1792,14 +1763,14 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) if (cosa->busmaster) { unsigned long addr = virt_to_bus(cosa->txbuf); int count=0; - printk(KERN_INFO "busmaster IRQ\n"); + pr_info("busmaster IRQ\n"); while (!(cosa_getstatus(cosa)&SR_TX_RDY)) { count++; udelay(10); if (count > 1000) break; } - printk(KERN_INFO "status %x\n", cosa_getstatus(cosa)); - printk(KERN_INFO "ready after %d loops\n", count); + pr_info("status %x\n", cosa_getstatus(cosa)); + pr_info("ready after %d loops\n", count); cosa_putdata16(cosa, (addr >> 16)&0xffff); count = 0; @@ -1808,7 +1779,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) if (count > 1000) break; udelay(10); } - printk(KERN_INFO "ready after %d loops\n", count); + pr_info("ready after %d loops\n", count); cosa_putdata16(cosa, addr &0xffff); flags1 = claim_dma_lock(); set_dma_mode(cosa->dma, DMA_MODE_CASCADE); @@ -1836,7 +1807,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status) { unsigned long flags; #ifdef DEBUG_IRQS - printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num); + pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num); #endif spin_lock_irqsave(&cosa->lock, flags); @@ -1859,7 +1830,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status) debug_data_in(cosa, cosa->rxsize & 0xff); #endif #if 0 - printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n", + pr_info("cosa%d: receive rxsize = (0x%04x)\n", cosa->num, cosa->rxsize); #endif } @@ -1869,12 +1840,12 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status) debug_data_in(cosa, cosa->rxsize); #endif #if 0 - printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n", + pr_info("cosa%d: receive rxsize = (0x%04x)\n", cosa->num, cosa->rxsize); #endif } if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) { - printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n", + pr_warn("%s: rx for unknown channel (0x%04x)\n", cosa->name, cosa->rxsize); spin_unlock_irqrestore(&cosa->lock, flags); goto reject; @@ -1889,7 +1860,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status) if (!cosa->rxbuf) { reject: /* Reject the packet */ - printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n", + pr_info("cosa%d: rejecting packet on channel %d\n", cosa->num, cosa->rxchan->num); cosa->rxbuf = cosa->bouncebuf; } @@ -1936,11 +1907,11 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status) #ifdef DEBUG_DATA { int i; - printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num, - cosa->rxchan->num, cosa->rxsize); + pr_info("cosa%dc%d: done rx(0x%x)", + cosa->num, cosa->rxchan->num, cosa->rxsize); for (i=0; i<cosa->rxsize; i++) - printk (" %02x", cosa->rxbuf[i]&0xff); - printk("\n"); + pr_cont(" %02x", cosa->rxbuf[i]&0xff); + pr_cont("\n"); } #endif /* Packet for unknown channel? */ @@ -1952,8 +1923,7 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status) if (cosa->rxchan->rx_done(cosa->rxchan)) clear_bit(cosa->rxchan->num, &cosa->rxbitmap); } else { - printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n", - cosa->num); + pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num); } /* * Clear the RXBIT, TXBIT and IRQBIT (the latest should be @@ -1975,8 +1945,7 @@ static irqreturn_t cosa_interrupt(int irq, void *cosa_) again: status = cosa_getstatus(cosa); #ifdef DEBUG_IRQS - printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num, - status & 0xff); + pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff); #endif #ifdef DEBUG_IO debug_status_in(cosa, status); @@ -1997,15 +1966,15 @@ again: udelay(100); goto again; } - printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n", + pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n", cosa->num, status & 0xff, count); } #ifdef DEBUG_IRQS if (count) - printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n", + pr_info("%s: %d-times got unknown status in IRQ\n", cosa->name, count); else - printk(KERN_INFO "%s: returning from IRQ\n", cosa->name); + pr_info("%s: returning from IRQ\n", cosa->name); #endif return IRQ_HANDLED; } @@ -2022,7 +1991,7 @@ again: static void debug_status_in(struct cosa_data *cosa, int status) { char *s; - switch(status & SR_CMD_FROM_SRP_MASK) { + switch (status & SR_CMD_FROM_SRP_MASK) { case SR_UP_REQUEST: s = "RX_REQ"; break; @@ -2036,41 +2005,41 @@ static void debug_status_in(struct cosa_data *cosa, int status) s = "NO_REQ"; break; } - printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n", + pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n", cosa->name, status, - status & SR_USR_RQ ? "USR_RQ|":"", - status & SR_TX_RDY ? "TX_RDY|":"", - status & SR_RX_RDY ? "RX_RDY|":"", + status & SR_USR_RQ ? "USR_RQ|" : "", + status & SR_TX_RDY ? "TX_RDY|" : "", + status & SR_RX_RDY ? "RX_RDY|" : "", s); } static void debug_status_out(struct cosa_data *cosa, int status) { - printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n", + pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n", cosa->name, status, - status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|", - status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|", - status & SR_RST ? "RESET|":"", - status & SR_USR_INT_ENA ? "USRINT|":"!usrint|", - status & SR_TX_INT_ENA ? "TXINT|":"!txint|", - status & SR_RX_INT_ENA ? "RXINT":"!rxint"); + status & SR_RX_DMA_ENA ? "RXDMA|" : "!rxdma|", + status & SR_TX_DMA_ENA ? "TXDMA|" : "!txdma|", + status & SR_RST ? "RESET|" : "", + status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|", + status & SR_TX_INT_ENA ? "TXINT|" : "!txint|", + status & SR_RX_INT_ENA ? "RXINT" : "!rxint"); } static void debug_data_in(struct cosa_data *cosa, int data) { - printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data); + pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data); } static void debug_data_out(struct cosa_data *cosa, int data) { - printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data); + pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data); } static void debug_data_cmd(struct cosa_data *cosa, int data) { - printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n", + pr_info("%s: IO: data <- 0x%04x (%s|%s)\n", cosa->name, data, data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy", data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy"); diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c deleted file mode 100644 index d14e6678dee..00000000000 --- a/drivers/net/wan/cycx_drv.c +++ /dev/null @@ -1,576 +0,0 @@ -/* -* cycx_drv.c Cyclom 2X Support Module. -* -* This module is a library of common hardware specific -* functions used by the Cyclades Cyclom 2X sync card. -* -* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br> -* -* Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo -* -* Based on sdladrv.c by Gene Kozin <genek@compuserve.com> -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version -* 2 of the License, or (at your option) any later version. -* ============================================================================ -* 1999/11/11 acme set_current_state(TASK_INTERRUPTIBLE), code -* cleanup -* 1999/11/08 acme init_cyc2x deleted, doing nothing -* 1999/11/06 acme back to read[bw], write[bw] and memcpy_to and -* fromio to use dpmbase ioremaped -* 1999/10/26 acme use isa_read[bw], isa_write[bw] & isa_memcpy_to -* & fromio -* 1999/10/23 acme cleanup to only supports cyclom2x: all the other -* boards are no longer manufactured by cyclades, -* if someone wants to support them... be my guest! -* 1999/05/28 acme cycx_intack & cycx_intde gone for good -* 1999/05/18 acme lots of unlogged work, submitting to Linus... -* 1999/01/03 acme more judicious use of data types -* 1999/01/03 acme judicious use of data types :> -* cycx_inten trying to reset pending interrupts -* from cyclom 2x - I think this isn't the way to -* go, but for now... -* 1999/01/02 acme cycx_intack ok, I think there's nothing to do -* to ack an int in cycx_drv.c, only handle it in -* cyx_isr (or in the other protocols: cyp_isr, -* cyf_isr, when they get implemented. -* Dec 31, 1998 acme cycx_data_boot & cycx_code_boot fixed, crossing -* fingers to see x25_configure in cycx_x25.c -* work... :) -* Dec 26, 1998 acme load implementation fixed, seems to work! :) -* cycx_2x_dpmbase_options with all the possible -* DPM addresses (20). -* cycx_intr implemented (test this!) -* general code cleanup -* Dec 8, 1998 Ivan Passos Cyclom-2X firmware load implementation. -* Aug 8, 1998 acme Initial version. -*/ - -#include <linux/init.h> /* __init */ -#include <linux/module.h> -#include <linux/kernel.h> /* printk(), and other useful stuff */ -#include <linux/stddef.h> /* offsetof(), etc. */ -#include <linux/errno.h> /* return codes */ -#include <linux/cycx_drv.h> /* API definitions */ -#include <linux/cycx_cfm.h> /* CYCX firmware module definitions */ -#include <linux/delay.h> /* udelay, msleep_interruptible */ -#include <asm/io.h> /* read[wl], write[wl], ioremap, iounmap */ - -#define MOD_VERSION 0 -#define MOD_RELEASE 6 - -MODULE_AUTHOR("Arnaldo Carvalho de Melo"); -MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver"); -MODULE_LICENSE("GPL"); - -/* Hardware-specific functions */ -static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len); -static void cycx_bootcfg(struct cycx_hw *hw); - -static int reset_cyc2x(void __iomem *addr); -static int detect_cyc2x(void __iomem *addr); - -/* Miscellaneous functions */ -static int get_option_index(long *optlist, long optval); -static u16 checksum(u8 *buf, u32 len); - -#define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET) - -/* Global Data */ - -/* private data */ -static char modname[] = "cycx_drv"; -static char fullname[] = "Cyclom 2X Support Module"; -static char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo " - "<acme@conectiva.com.br>"; - -/* Hardware configuration options. - * These are arrays of configuration options used by verification routines. - * The first element of each array is its size (i.e. number of options). - */ -static long cyc2x_dpmbase_options[] = { - 20, - 0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000, - 0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000, 0xD0000, 0xD4000, - 0xD8000, 0xDC000, 0xE0000, 0xE4000, 0xE8000, 0xEC000 -}; - -static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 }; - -/* Kernel Loadable Module Entry Points */ -/* Module 'insert' entry point. - * o print announcement - * o initialize static data - * - * Return: 0 Ok - * < 0 error. - * Context: process */ - -static int __init cycx_drv_init(void) -{ - printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE, - copyright); - - return 0; -} - -/* Module 'remove' entry point. - * o release all remaining system resources */ -static void cycx_drv_cleanup(void) -{ -} - -/* Kernel APIs */ -/* Set up adapter. - * o detect adapter type - * o verify hardware configuration options - * o check for hardware conflicts - * o set up adapter shared memory - * o test adapter memory - * o load firmware - * Return: 0 ok. - * < 0 error */ -EXPORT_SYMBOL(cycx_setup); -int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase) -{ - int err; - - /* Verify IRQ configuration options */ - if (!get_option_index(cycx_2x_irq_options, hw->irq)) { - printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq); - return -EINVAL; - } - - /* Setup adapter dual-port memory window and test memory */ - if (!dpmbase) { - printk(KERN_ERR "%s: you must specify the dpm address!\n", - modname); - return -EINVAL; - } else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) { - printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n", - modname, dpmbase); - return -EINVAL; - } - - hw->dpmbase = ioremap(dpmbase, CYCX_WINDOWSIZE); - hw->dpmsize = CYCX_WINDOWSIZE; - - if (!detect_cyc2x(hw->dpmbase)) { - printk(KERN_ERR "%s: adapter Cyclom 2X not found at " - "address 0x%lX!\n", modname, dpmbase); - return -EINVAL; - } - - printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n", - modname, dpmbase); - - /* Load firmware. If loader fails then shut down adapter */ - err = load_cyc2x(hw, cfm, len); - - if (err) - cycx_down(hw); /* shutdown adapter */ - - return err; -} - -EXPORT_SYMBOL(cycx_down); -int cycx_down(struct cycx_hw *hw) -{ - iounmap(hw->dpmbase); - return 0; -} - -/* Enable interrupt generation. */ -static void cycx_inten(struct cycx_hw *hw) -{ - writeb(0, hw->dpmbase); -} - -/* Generate an interrupt to adapter's CPU. */ -EXPORT_SYMBOL(cycx_intr); -void cycx_intr(struct cycx_hw *hw) -{ - writew(0, hw->dpmbase + GEN_CYCX_INTR); -} - -/* Execute Adapter Command. - * o Set exec flag. - * o Busy-wait until flag is reset. */ -EXPORT_SYMBOL(cycx_exec); -int cycx_exec(void __iomem *addr) -{ - u16 i = 0; - /* wait till addr content is zeroed */ - - while (readw(addr)) { - udelay(1000); - - if (++i > 50) - return -1; - } - - return 0; -} - -/* Read absolute adapter memory. - * Transfer data from adapter's memory to data buffer. */ -EXPORT_SYMBOL(cycx_peek); -int cycx_peek(struct cycx_hw *hw, u32 addr, void *buf, u32 len) -{ - if (len == 1) - *(u8*)buf = readb(hw->dpmbase + addr); - else - memcpy_fromio(buf, hw->dpmbase + addr, len); - - return 0; -} - -/* Write Absolute Adapter Memory. - * Transfer data from data buffer to adapter's memory. */ -EXPORT_SYMBOL(cycx_poke); -int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len) -{ - if (len == 1) - writeb(*(u8*)buf, hw->dpmbase + addr); - else - memcpy_toio(hw->dpmbase + addr, buf, len); - - return 0; -} - -/* Hardware-Specific Functions */ - -/* Load Aux Routines */ -/* Reset board hardware. - return 1 if memory exists at addr and 0 if not. */ -static int memory_exists(void __iomem *addr) -{ - int tries = 0; - - for (; tries < 3 ; tries++) { - writew(TEST_PATTERN, addr + 0x10); - - if (readw(addr + 0x10) == TEST_PATTERN) - if (readw(addr + 0x10) == TEST_PATTERN) - return 1; - - msleep_interruptible(1 * 1000); - } - - return 0; -} - -/* Load reset code. */ -static void reset_load(void __iomem *addr, u8 *buffer, u32 cnt) -{ - void __iomem *pt_code = addr + RESET_OFFSET; - u16 i; /*, j; */ - - for (i = 0 ; i < cnt ; i++) { -/* for (j = 0 ; j < 50 ; j++); Delay - FIXME busy waiting... */ - writeb(*buffer++, pt_code++); - } -} - -/* Load buffer using boot interface. - * o copy data from buffer to Cyclom-X memory - * o wait for reset code to copy it to right portion of memory */ -static int buffer_load(void __iomem *addr, u8 *buffer, u32 cnt) -{ - memcpy_toio(addr + DATA_OFFSET, buffer, cnt); - writew(GEN_BOOT_DAT, addr + CMD_OFFSET); - - return wait_cyc(addr); -} - -/* Set up entry point and kick start Cyclom-X CPU. */ -static void cycx_start(void __iomem *addr) -{ - /* put in 0x30 offset the jump instruction to the code entry point */ - writeb(0xea, addr + 0x30); - writeb(0x00, addr + 0x31); - writeb(0xc4, addr + 0x32); - writeb(0x00, addr + 0x33); - writeb(0x00, addr + 0x34); - - /* cmd to start executing code */ - writew(GEN_START, addr + CMD_OFFSET); -} - -/* Load and boot reset code. */ -static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len) -{ - void __iomem *pt_start = addr + START_OFFSET; - - writeb(0xea, pt_start++); /* jmp to f000:3f00 */ - writeb(0x00, pt_start++); - writeb(0xfc, pt_start++); - writeb(0x00, pt_start++); - writeb(0xf0, pt_start); - reset_load(addr, code, len); - - /* 80186 was in hold, go */ - writeb(0, addr + START_CPU); - msleep_interruptible(1 * 1000); -} - -/* Load data.bin file through boot (reset) interface. */ -static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len) -{ - void __iomem *pt_boot_cmd = addr + CMD_OFFSET; - u32 i; - - /* boot buffer length */ - writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); - writew(GEN_DEFPAR, pt_boot_cmd); - - if (wait_cyc(addr) < 0) - return -1; - - writew(0, pt_boot_cmd + sizeof(u16)); - writew(0x4000, pt_boot_cmd + 2 * sizeof(u16)); - writew(GEN_SET_SEG, pt_boot_cmd); - - if (wait_cyc(addr) < 0) - return -1; - - for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) - if (buffer_load(addr, code + i, - min_t(u32, CFM_LOAD_BUFSZ, (len - i))) < 0) { - printk(KERN_ERR "%s: Error !!\n", modname); - return -1; - } - - return 0; -} - - -/* Load code.bin file through boot (reset) interface. */ -static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len) -{ - void __iomem *pt_boot_cmd = addr + CMD_OFFSET; - u32 i; - - /* boot buffer length */ - writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); - writew(GEN_DEFPAR, pt_boot_cmd); - - if (wait_cyc(addr) < 0) - return -1; - - writew(0x0000, pt_boot_cmd + sizeof(u16)); - writew(0xc400, pt_boot_cmd + 2 * sizeof(u16)); - writew(GEN_SET_SEG, pt_boot_cmd); - - if (wait_cyc(addr) < 0) - return -1; - - for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) - if (buffer_load(addr, code + i, - min_t(u32, CFM_LOAD_BUFSZ, (len - i)))) { - printk(KERN_ERR "%s: Error !!\n", modname); - return -1; - } - - return 0; -} - -/* Load adapter from the memory image of the CYCX firmware module. - * o verify firmware integrity and compatibility - * o start adapter up */ -static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) -{ - int i, j; - struct cycx_fw_header *img_hdr; - u8 *reset_image, - *data_image, - *code_image; - void __iomem *pt_cycld = hw->dpmbase + 0x400; - u16 cksum; - - /* Announce */ - printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname, - cfm->signature); - - /* Verify firmware signature */ - if (strcmp(cfm->signature, CFM_SIGNATURE)) { - printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n", - modname); - return -EINVAL; - } - - printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version); - - /* Verify firmware module format version */ - if (cfm->version != CFM_VERSION) { - printk(KERN_ERR "%s:%s: firmware format %u rejected! " - "Expecting %u.\n", - modname, __FUNCTION__, cfm->version, CFM_VERSION); - return -EINVAL; - } - - /* Verify firmware module length and checksum */ - cksum = checksum((u8*)&cfm->info, sizeof(struct cycx_fw_info) + - cfm->info.codesize); -/* - FIXME cfm->info.codesize is off by 2 - if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) || -*/ - if (cksum != cfm->checksum) { - printk(KERN_ERR "%s:%s: firmware corrupted!\n", - modname, __FUNCTION__); - printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n", - len - (int)sizeof(struct cycx_firmware) - 1, - cfm->info.codesize); - printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n", - cksum, cfm->checksum); - return -EINVAL; - } - - /* If everything is ok, set reset, data and code pointers */ - img_hdr = (struct cycx_fw_header *)&cfm->image; -#ifdef FIRMWARE_DEBUG - printk(KERN_INFO "%s:%s: image sizes\n", __FUNCTION__, modname); - printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size); - printk(KERN_INFO " data=%lu\n", img_hdr->data_size); - printk(KERN_INFO " code=%lu\n", img_hdr->code_size); -#endif - reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header); - data_image = reset_image + img_hdr->reset_size; - code_image = data_image + img_hdr->data_size; - - /*---- Start load ----*/ - /* Announce */ - printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname, - cfm->descr[0] ? cfm->descr : "unknown firmware", - cfm->info.codeid); - - for (i = 0 ; i < 5 ; i++) { - /* Reset Cyclom hardware */ - if (!reset_cyc2x(hw->dpmbase)) { - printk(KERN_ERR "%s: dpm problem or board not found\n", - modname); - return -EINVAL; - } - - /* Load reset.bin */ - cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size); - /* reset is waiting for boot */ - writew(GEN_POWER_ON, pt_cycld); - msleep_interruptible(1 * 1000); - - for (j = 0 ; j < 3 ; j++) - if (!readw(pt_cycld)) - goto reset_loaded; - else - msleep_interruptible(1 * 1000); - } - - printk(KERN_ERR "%s: reset not started.\n", modname); - return -EINVAL; - -reset_loaded: - /* Load data.bin */ - if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) { - printk(KERN_ERR "%s: cannot load data file.\n", modname); - return -EINVAL; - } - - /* Load code.bin */ - if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) { - printk(KERN_ERR "%s: cannot load code file.\n", modname); - return -EINVAL; - } - - /* Prepare boot-time configuration data */ - cycx_bootcfg(hw); - - /* kick-off CPU */ - cycx_start(hw->dpmbase); - - /* Arthur Ganzert's tip: wait a while after the firmware loading... - seg abr 26 17:17:12 EST 1999 - acme */ - msleep_interruptible(7 * 1000); - printk(KERN_INFO "%s: firmware loaded!\n", modname); - - /* enable interrupts */ - cycx_inten(hw); - - return 0; -} - -/* Prepare boot-time firmware configuration data. - * o initialize configuration data area - From async.doc - V_3.4.0 - 07/18/1994 - - As of now, only static buffers are available to the user. - So, the bit VD_RXDIRC must be set in 'valid'. That means that user - wants to use the static transmission and reception buffers. */ -static void cycx_bootcfg(struct cycx_hw *hw) -{ - /* use fixed buffers */ - writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); -} - -/* Detect Cyclom 2x adapter. - * Following tests are used to detect Cyclom 2x adapter: - * to be completed based on the tests done below - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. */ -static int detect_cyc2x(void __iomem *addr) -{ - reset_cyc2x(addr); - - return memory_exists(addr); -} - -/* Miscellaneous */ -/* Get option's index into the options list. - * Return option's index (1 .. N) or zero if option is invalid. */ -static int get_option_index(long *optlist, long optval) -{ - int i = 1; - - for (; i <= optlist[0]; ++i) - if (optlist[i] == optval) - return i; - - return 0; -} - -/* Reset adapter's CPU. */ -static int reset_cyc2x(void __iomem *addr) -{ - writeb(0, addr + RST_ENABLE); - msleep_interruptible(2 * 1000); - writeb(0, addr + RST_DISABLE); - msleep_interruptible(2 * 1000); - - return memory_exists(addr); -} - -/* Calculate 16-bit CRC using CCITT polynomial. */ -static u16 checksum(u8 *buf, u32 len) -{ - u16 crc = 0; - u16 mask, flag; - - for (; len; --len, ++buf) - for (mask = 0x80; mask; mask >>= 1) { - flag = (crc & 0x8000); - crc <<= 1; - crc |= ((*buf & mask) ? 1 : 0); - - if (flag) - crc ^= 0x1021; - } - - return crc; -} - -module_init(cycx_drv_init); -module_exit(cycx_drv_cleanup); - -/* End */ diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c deleted file mode 100644 index a0e8611ad8e..00000000000 --- a/drivers/net/wan/cycx_main.c +++ /dev/null @@ -1,348 +0,0 @@ -/* -* cycx_main.c Cyclades Cyclom 2X WAN Link Driver. Main module. -* -* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br> -* -* Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo -* -* Based on sdlamain.c by Gene Kozin <genek@compuserve.com> & -* Jaspreet Singh <jaspreet@sangoma.com> -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version -* 2 of the License, or (at your option) any later version. -* ============================================================================ -* Please look at the bitkeeper changelog (or any other scm tool that ends up -* importing bitkeeper changelog or that replaces bitkeeper in the future as -* main tool for linux development). -* -* 2001/05/09 acme Fix MODULE_DESC for debug, .bss nitpicks, -* some cleanups -* 2000/07/13 acme remove useless #ifdef MODULE and crap -* #if KERNEL_VERSION > blah -* 2000/07/06 acme __exit at cyclomx_cleanup -* 2000/04/02 acme dprintk and cycx_debug -* module_init/module_exit -* 2000/01/21 acme rename cyclomx_open to cyclomx_mod_inc_use_count -* and cyclomx_close to cyclomx_mod_dec_use_count -* 2000/01/08 acme cleanup -* 1999/11/06 acme cycx_down back to life (it needs to be -* called to iounmap the dpmbase) -* 1999/08/09 acme removed references to enable_tx_int -* use spinlocks instead of cli/sti in -* cyclomx_set_state -* 1999/05/19 acme works directly linked into the kernel -* init_waitqueue_head for 2.3.* kernel -* 1999/05/18 acme major cleanup (polling not needed), etc -* 1998/08/28 acme minor cleanup (ioctls for firmware deleted) -* queue_task activated -* 1998/08/08 acme Initial version. -*/ - -#include <linux/stddef.h> /* offsetof(), etc. */ -#include <linux/errno.h> /* return codes */ -#include <linux/string.h> /* inline memset(), etc. */ -#include <linux/slab.h> /* kmalloc(), kfree() */ -#include <linux/kernel.h> /* printk(), and other useful stuff */ -#include <linux/module.h> /* support for loadable modules */ -#include <linux/ioport.h> /* request_region(), release_region() */ -#include <linux/wanrouter.h> /* WAN router definitions */ -#include <linux/cyclomx.h> /* cyclomx common user API definitions */ -#include <linux/init.h> /* __init (when not using as a module) */ - -unsigned int cycx_debug; - -MODULE_AUTHOR("Arnaldo Carvalho de Melo"); -MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver."); -MODULE_LICENSE("GPL"); -module_param(cycx_debug, int, 0); -MODULE_PARM_DESC(cycx_debug, "cyclomx debug level"); - -/* Defines & Macros */ - -#define CYCX_DRV_VERSION 0 /* version number */ -#define CYCX_DRV_RELEASE 11 /* release (minor version) number */ -#define CYCX_MAX_CARDS 1 /* max number of adapters */ - -#define CONFIG_CYCX_CARDS 1 - -/* Function Prototypes */ - -/* WAN link driver entry points */ -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); - -/* Global Data - * Note: All data must be explicitly initialized!!! - */ - -/* private data */ -static char cycx_drvname[] = "cyclomx"; -static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver"; -static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo " - "<acme@conectiva.com.br>"; -static int cycx_ncards = CONFIG_CYCX_CARDS; -static struct cycx_device *cycx_card_array; /* adapter data space */ - -/* Kernel Loadable Module Entry Points */ - -/* - * Module 'insert' entry point. - * o print announcement - * o allocate adapter data space - * o initialize static data - * o register all cards with WAN router - * o calibrate Cyclom 2X shared memory access delay. - * - * Return: 0 Ok - * < 0 error. - * Context: process - */ -static int __init cycx_init(void) -{ - int cnt, err = -ENOMEM; - - printk(KERN_INFO "%s v%u.%u %s\n", - cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE, - cycx_copyright); - - /* Verify number of cards and allocate adapter data space */ - cycx_ncards = min_t(int, cycx_ncards, CYCX_MAX_CARDS); - cycx_ncards = max_t(int, cycx_ncards, 1); - cycx_card_array = kcalloc(cycx_ncards, sizeof(struct cycx_device), GFP_KERNEL); - if (!cycx_card_array) - goto out; - - - /* Register adapters with WAN router */ - for (cnt = 0; cnt < cycx_ncards; ++cnt) { - struct cycx_device *card = &cycx_card_array[cnt]; - struct wan_device *wandev = &card->wandev; - - sprintf(card->devname, "%s%d", cycx_drvname, cnt + 1); - wandev->magic = ROUTER_MAGIC; - wandev->name = card->devname; - wandev->private = card; - wandev->setup = cycx_wan_setup; - wandev->shutdown = cycx_wan_shutdown; - err = register_wan_device(wandev); - - if (err) { - printk(KERN_ERR "%s: %s registration failed with " - "error %d!\n", - cycx_drvname, card->devname, err); - break; - } - } - - err = -ENODEV; - if (!cnt) { - kfree(cycx_card_array); - goto out; - } - err = 0; - cycx_ncards = cnt; /* adjust actual number of cards */ -out: return err; -} - -/* - * Module 'remove' entry point. - * o unregister all adapters from the WAN router - * o release all remaining system resources - */ -static void __exit cycx_exit(void) -{ - int i = 0; - - for (; i < cycx_ncards; ++i) { - struct cycx_device *card = &cycx_card_array[i]; - unregister_wan_device(card->devname); - } - - kfree(cycx_card_array); -} - -/* WAN Device Driver Entry Points */ -/* - * Setup/configure WAN link driver. - * o check adapter state - * o make sure firmware is present in configuration - * o allocate interrupt vector - * o setup Cyclom 2X hardware - * o call appropriate routine to perform protocol-specific initialization - * - * This function is called when router handles ROUTER_SETUP IOCTL. The - * configuration structure is in kernel memory (including extended data, if - * any). - */ -static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf) -{ - int rc = -EFAULT; - struct cycx_device *card; - int irq; - - /* Sanity checks */ - - if (!wandev || !wandev->private || !conf) - goto out; - - card = wandev->private; - rc = -EBUSY; - if (wandev->state != WAN_UNCONFIGURED) - goto out; - - rc = -EINVAL; - if (!conf->data_size || !conf->data) { - printk(KERN_ERR "%s: firmware not found in configuration " - "data!\n", wandev->name); - goto out; - } - - if (conf->irq <= 0) { - printk(KERN_ERR "%s: can't configure without IRQ!\n", - wandev->name); - goto out; - } - - /* Allocate IRQ */ - irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */ - - if (request_irq(irq, cycx_isr, 0, wandev->name, card)) { - printk(KERN_ERR "%s: can't reserve IRQ %d!\n", - wandev->name, irq); - goto out; - } - - /* Configure hardware, load firmware, etc. */ - memset(&card->hw, 0, sizeof(card->hw)); - card->hw.irq = irq; - card->hw.dpmsize = CYCX_WINDOWSIZE; - card->hw.fwid = CFID_X25_2X; - spin_lock_init(&card->lock); - init_waitqueue_head(&card->wait_stats); - - rc = cycx_setup(&card->hw, conf->data, conf->data_size, conf->maddr); - if (rc) - goto out_irq; - - /* Initialize WAN device data space */ - wandev->irq = irq; - wandev->dma = wandev->ioport = 0; - wandev->maddr = (unsigned long)card->hw.dpmbase; - wandev->msize = card->hw.dpmsize; - wandev->hw_opt[2] = 0; - wandev->hw_opt[3] = card->hw.fwid; - - /* Protocol-specific initialization */ - switch (card->hw.fwid) { -#ifdef CONFIG_CYCLOMX_X25 - case CFID_X25_2X: - rc = cycx_x25_wan_init(card, conf); - break; -#endif - default: - printk(KERN_ERR "%s: this firmware is not supported!\n", - wandev->name); - rc = -EINVAL; - } - - if (rc) { - cycx_down(&card->hw); - goto out_irq; - } - - rc = 0; -out: - return rc; -out_irq: - free_irq(irq, card); - goto out; -} - -/* - * Shut down WAN link driver. - * o shut down adapter hardware - * o release system resources. - * - * This function is called by the router when device is being unregistered or - * when it handles ROUTER_DOWN IOCTL. - */ -static int cycx_wan_shutdown(struct wan_device *wandev) -{ - int ret = -EFAULT; - struct cycx_device *card; - - /* sanity checks */ - if (!wandev || !wandev->private) - goto out; - - ret = 0; - if (wandev->state == WAN_UNCONFIGURED) - goto out; - - card = wandev->private; - wandev->state = WAN_UNCONFIGURED; - cycx_down(&card->hw); - printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name, - wandev->irq); - free_irq(wandev->irq, card); -out: return ret; -} - -/* Miscellaneous */ -/* - * Cyclom 2X Interrupt Service Routine. - * 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 cycx_device *card = dev_id; - - if (card->wandev.state == WAN_UNCONFIGURED) - goto out; - - if (card->in_isr) { - printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n", - card->devname, card->wandev.irq); - goto out; - } - - if (card->isr) - card->isr(card); - return IRQ_HANDLED; -out: - return IRQ_NONE; -} - -/* Set WAN device state. */ -void cycx_set_state(struct cycx_device *card, int state) -{ - unsigned long flags; - char *string_state = NULL; - - spin_lock_irqsave(&card->lock, flags); - - if (card->wandev.state != state) { - switch (state) { - case WAN_CONNECTED: - string_state = "connected!"; - break; - case WAN_DISCONNECTED: - string_state = "disconnected!"; - break; - } - printk(KERN_INFO "%s: link %s\n", card->devname, string_state); - card->wandev.state = state; - } - - card->state_tick = jiffies; - spin_unlock_irqrestore(&card->lock, flags); -} - -module_init(cycx_init); -module_exit(cycx_exit); diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c deleted file mode 100644 index d3b28b01b9f..00000000000 --- a/drivers/net/wan/cycx_x25.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* -* cycx_x25.c Cyclom 2X WAN Link Driver. X.25 module. -* -* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br> -* -* Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo -* -* Based on sdla_x25.c by Gene Kozin <genek@compuserve.com> -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version -* 2 of the License, or (at your option) any later version. -* ============================================================================ -* 2001/01/12 acme use dev_kfree_skb_irq on interrupt context -* 2000/04/02 acme dprintk, cycx_debug -* fixed the bug introduced in get_dev_by_lcn and -* get_dev_by_dte_addr by the anonymous hacker -* that converted this driver to softnet -* 2000/01/08 acme cleanup -* 1999/10/27 acme use ARPHRD_HWX25 so that the X.25 stack know -* that we have a X.25 stack implemented in -* firmware onboard -* 1999/10/18 acme support for X.25 sockets in if_send, -* beware: socket(AF_X25...) IS WORK IN PROGRESS, -* TCP/IP over X.25 via wanrouter not affected, -* working. -* 1999/10/09 acme chan_disc renamed to chan_disconnect, -* began adding support for X.25 sockets: -* conf->protocol in new_if -* 1999/10/05 acme fixed return E... to return -E... -* 1999/08/10 acme serialized access to the card thru a spinlock -* in x25_exec -* 1999/08/09 acme removed per channel spinlocks -* removed references to enable_tx_int -* 1999/05/28 acme fixed nibble_to_byte, ackvc now properly treated -* if_send simplified -* 1999/05/25 acme fixed t1, t2, t21 & t23 configuration -* use spinlocks instead of cli/sti in some points -* 1999/05/24 acme finished the x25_get_stat function -* 1999/05/23 acme dev->type = ARPHRD_X25 (tcpdump only works, -* AFAIT, with ARPHRD_ETHER). This seems to be -* needed to use socket(AF_X25)... -* Now the config file must specify a peer media -* address for svc channels over a crossover cable. -* Removed hold_timeout from x25_channel_t, -* not used. -* A little enhancement in the DEBUG processing -* 1999/05/22 acme go to DISCONNECTED in disconnect_confirm_intr, -* instead of chan_disc. -* 1999/05/16 marcelo fixed timer initialization in SVCs -* 1999/01/05 acme x25_configure now get (most of) all -* parameters... -* 1999/01/05 acme pktlen now (correctly) uses log2 (value -* configured) -* 1999/01/03 acme judicious use of data types (u8, u16, u32, etc) -* 1999/01/03 acme cyx_isr: reset dpmbase to acknowledge -* indication (interrupt from cyclom 2x) -* 1999/01/02 acme cyx_isr: first hackings... -* 1999/01/0203 acme when initializing an array don't give less -* elements than declared... -* example: char send_cmd[6] = "?\xFF\x10"; -* you'll gonna lose a couple hours, 'cause your -* brain won't admit that there's an error in the -* above declaration... the side effect is that -* memset is put into the unresolved symbols -* instead of using the inline memset functions... -* 1999/01/02 acme began chan_connect, chan_send, x25_send -* 1998/12/31 acme x25_configure -* this code can be compiled as non module -* 1998/12/27 acme code cleanup -* IPX code wiped out! let's decrease code -* complexity for now, remember: I'm learning! :) -* bps_to_speed_code OK -* 1998/12/26 acme Minimal debug code cleanup -* 1998/08/08 acme Initial version. -*/ - -#define CYCLOMX_X25_DEBUG 1 - -#include <linux/ctype.h> /* isdigit() */ -#include <linux/errno.h> /* return codes */ -#include <linux/if_arp.h> /* ARPHRD_HWX25 */ -#include <linux/kernel.h> /* printk(), and other useful stuff */ -#include <linux/module.h> -#include <linux/string.h> /* inline memset(), etc. */ -#include <linux/slab.h> /* kmalloc(), kfree() */ -#include <linux/stddef.h> /* offsetof(), etc. */ -#include <linux/wanrouter.h> /* WAN router definitions */ - -#include <asm/byteorder.h> /* htons(), etc. */ - -#include <linux/cyclomx.h> /* Cyclom 2X common user API definitions */ -#include <linux/cycx_x25.h> /* X.25 firmware API definitions */ - -#include <net/x25device.h> - -/* Defines & Macros */ -#define CYCX_X25_MAX_CMD_RETRY 5 -#define CYCX_X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */ - -/* Data Structures */ -/* This is an extension of the 'struct net_device' we create for each network - interface to keep the rest of X.25 channel-specific data. */ -struct cycx_x25_channel { - /* This member must be first. */ - struct net_device *slave; /* WAN slave */ - - char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */ - char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */ - char *local_addr; /* local media address, ASCIIZ - - svc thru crossover cable */ - s16 lcn; /* logical channel number/conn.req.key*/ - u8 link; - struct timer_list timer; /* timer used for svc channel disc. */ - u16 protocol; /* ethertype, 0 - multiplexed */ - u8 svc; /* 0 - permanent, 1 - switched */ - u8 state; /* channel state */ - u8 drop_sequence; /* mark sequence for dropping */ - u32 idle_tmout; /* sec, before disconnecting */ - struct sk_buff *rx_skb; /* receive socket buffer */ - struct cycx_device *card; /* -> owner */ - struct net_device_stats ifstats;/* interface statistics */ -}; - -/* Function Prototypes */ -/* WAN link driver entry points. These are called by the WAN router module. */ -static int cycx_wan_update(struct wan_device *wandev), - cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev, - wanif_conf_t *conf), - cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev); - -/* Network device interface */ -static int cycx_netdevice_init(struct net_device *dev); -static int cycx_netdevice_open(struct net_device *dev); -static int cycx_netdevice_stop(struct net_device *dev); -static int cycx_netdevice_hard_header(struct sk_buff *skb, - struct net_device *dev, u16 type, - const void *daddr, const void *saddr, - unsigned len); -static int cycx_netdevice_rebuild_header(struct sk_buff *skb); -static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev); - -static struct net_device_stats * - cycx_netdevice_get_stats(struct net_device *dev); - -/* Interrupt handlers */ -static void cycx_x25_irq_handler(struct cycx_device *card), - cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd), - cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd), - cycx_x25_irq_log(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_stat(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_connect_confirm(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_disconnect_confirm(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_connect(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_disconnect(struct cycx_device *card, - struct cycx_x25_cmd *cmd), - cycx_x25_irq_spurious(struct cycx_device *card, - struct cycx_x25_cmd *cmd); - -/* X.25 firmware interface functions */ -static int cycx_x25_configure(struct cycx_device *card, - struct cycx_x25_config *conf), - cycx_x25_get_stats(struct cycx_device *card), - cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm, - int len, void *buf), - cycx_x25_connect_response(struct cycx_device *card, - struct cycx_x25_channel *chan), - cycx_x25_disconnect_response(struct cycx_device *card, u8 link, - u8 lcn); - -/* channel functions */ -static int cycx_x25_chan_connect(struct net_device *dev), - cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb); - -static void cycx_x25_chan_disconnect(struct net_device *dev), - cycx_x25_chan_send_event(struct net_device *dev, u8 event); - -/* Miscellaneous functions */ -static void cycx_x25_set_chan_state(struct net_device *dev, u8 state), - cycx_x25_chan_timer(unsigned long d); - -static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble), - reset_timer(struct net_device *dev); - -static u8 bps_to_speed_code(u32 bps); -static u8 cycx_log2(u32 n); - -static unsigned dec_to_uint(u8 *str, int len); - -static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev, - s16 lcn); -static struct net_device * - cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte); - -#ifdef CYCLOMX_X25_DEBUG -static void hex_dump(char *msg, unsigned char *p, int len); -static void cycx_x25_dump_config(struct cycx_x25_config *conf); -static void cycx_x25_dump_stats(struct cycx_x25_stats *stats); -static void cycx_x25_dump_devs(struct wan_device *wandev); -#else -#define hex_dump(msg, p, len) -#define cycx_x25_dump_config(conf) -#define cycx_x25_dump_stats(stats) -#define cycx_x25_dump_devs(wandev) -#endif -/* Public Functions */ - -/* X.25 Protocol Initialization routine. - * - * This routine is called by the main Cyclom 2X module during setup. At this - * point adapter is completely initialized and X.25 firmware is running. - * o configure adapter - * o initialize protocol-specific fields of the adapter data space. - * - * Return: 0 o.k. - * < 0 failure. */ -int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf) -{ - struct cycx_x25_config cfg; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_X25) { - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - } - - /* Initialize protocol-specific fields */ - card->mbox = card->hw.dpmbase + X25_MBOX_OFFS; - card->u.x.connection_keys = 0; - spin_lock_init(&card->u.x.lock); - - /* Configure adapter. Here we set reasonable defaults, then parse - * device configuration structure and set configuration options. - * Most configuration options are verified and corrected (if - * necessary) since we can't rely on the adapter to do so and don't - * want it to fail either. */ - memset(&cfg, 0, sizeof(cfg)); - cfg.link = 0; - cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55; - cfg.speed = bps_to_speed_code(conf->bps); - cfg.n3win = 7; - cfg.n2win = 2; - cfg.n2 = 5; - cfg.nvc = 1; - cfg.npvc = 1; - cfg.flags = 0x02; /* default = V35 */ - cfg.t1 = 10; /* line carrier timeout */ - cfg.t2 = 29; /* tx timeout */ - cfg.t21 = 180; /* CALL timeout */ - cfg.t23 = 180; /* CLEAR timeout */ - - /* adjust MTU */ - if (!conf->mtu || conf->mtu >= 512) - card->wandev.mtu = 512; - else if (conf->mtu >= 256) - card->wandev.mtu = 256; - else if (conf->mtu >= 128) - card->wandev.mtu = 128; - else - card->wandev.mtu = 64; - - cfg.pktlen = cycx_log2(card->wandev.mtu); - - if (conf->station == WANOPT_DTE) { - cfg.locaddr = 3; /* DTE */ - cfg.remaddr = 1; /* DCE */ - } else { - cfg.locaddr = 1; /* DCE */ - cfg.remaddr = 3; /* DTE */ - } - - if (conf->interface == WANOPT_RS232) - cfg.flags = 0; /* FIXME just reset the 2nd bit */ - - if (conf->u.x25.hi_pvc) { - card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, 4095); - card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); - } - - if (conf->u.x25.hi_svc) { - card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, 4095); - card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); - } - - if (card->u.x.lo_pvc == 255) - cfg.npvc = 0; - else - cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1; - - cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc; - - if (conf->u.x25.hdlc_window) - cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7); - - if (conf->u.x25.pkt_window) - cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7); - - if (conf->u.x25.t1) - cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30); - - if (conf->u.x25.t2) - cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30); - - if (conf->u.x25.t11_t21) - cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30); - - if (conf->u.x25.t13_t23) - cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30); - - if (conf->u.x25.n2) - cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30); - - /* initialize adapter */ - if (cycx_x25_configure(card, &cfg)) - return -EIO; - - /* Initialize protocol-specific fields of adapter data space */ - card->wandev.bps = conf->bps; - card->wandev.interface = conf->interface; - card->wandev.clocking = conf->clocking; - card->wandev.station = conf->station; - card->isr = cycx_x25_irq_handler; - card->exec = NULL; - card->wandev.update = cycx_wan_update; - card->wandev.new_if = cycx_wan_new_if; - card->wandev.del_if = cycx_wan_del_if; - card->wandev.state = WAN_DISCONNECTED; - - return 0; -} - -/* WAN Device Driver Entry Points */ -/* Update device status & statistics. */ -static int cycx_wan_update(struct wan_device *wandev) -{ - /* sanity checks */ - if (!wandev || !wandev->private) - return -EFAULT; - - if (wandev->state == WAN_UNCONFIGURED) - return -ENODEV; - - cycx_x25_get_stats(wandev->private); - - return 0; -} - -/* Create new logical channel. - * This routine is called by the router when ROUTER_IFNEW IOCTL is being - * handled. - * o parse media- and hardware-specific configuration - * o make sure that a new channel can be created - * o allocate resources, if necessary - * o prepare network device structure for registration. - * - * Return: 0 o.k. - * < 0 failure (channel will not be created) */ -static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev, - wanif_conf_t *conf) -{ - struct cycx_device *card = wandev->private; - struct cycx_x25_channel *chan; - int err = 0; - - if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) { - printk(KERN_INFO "%s: invalid interface name!\n", - card->devname); - return -EINVAL; - } - - /* allocate and initialize private data */ - chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL); - if (!chan) - return -ENOMEM; - - strcpy(chan->name, conf->name); - chan->card = card; - chan->link = conf->port; - chan->protocol = conf->protocol ? ETH_P_X25 : ETH_P_IP; - chan->rx_skb = NULL; - /* only used in svc connected thru crossover cable */ - chan->local_addr = NULL; - - if (conf->addr[0] == '@') { /* SVC */ - int len = strlen(conf->local_addr); - - if (len) { - if (len > WAN_ADDRESS_SZ) { - printk(KERN_ERR "%s: %s local addr too long!\n", - wandev->name, chan->name); - kfree(chan); - return -EINVAL; - } else { - chan->local_addr = kmalloc(len + 1, GFP_KERNEL); - - if (!chan->local_addr) { - kfree(chan); - return -ENOMEM; - } - } - - strncpy(chan->local_addr, conf->local_addr, - WAN_ADDRESS_SZ); - } - - chan->svc = 1; - strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ); - init_timer(&chan->timer); - chan->timer.function = cycx_x25_chan_timer; - chan->timer.data = (unsigned long)dev; - - /* Set channel timeouts (default if not specified) */ - chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90; - } else if (isdigit(conf->addr[0])) { /* PVC */ - s16 lcn = dec_to_uint(conf->addr, 0); - - if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc) - chan->lcn = lcn; - else { - printk(KERN_ERR - "%s: PVC %u is out of range on interface %s!\n", - wandev->name, lcn, chan->name); - err = -EINVAL; - } - } else { - printk(KERN_ERR "%s: invalid media address on interface %s!\n", - wandev->name, chan->name); - err = -EINVAL; - } - - if (err) { - kfree(chan->local_addr); - kfree(chan); - return err; - } - - /* prepare network device data space for registration */ - strcpy(dev->name, chan->name); - dev->init = cycx_netdevice_init; - dev->priv = chan; - - return 0; -} - -/* Delete logical channel. */ -static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev) -{ - if (dev->priv) { - struct cycx_x25_channel *chan = dev->priv; - - if (chan->svc) { - kfree(chan->local_addr); - if (chan->state == WAN_CONNECTED) - del_timer(&chan->timer); - } - - kfree(chan); - dev->priv = NULL; - } - - return 0; -} - - -/* Network Device Interface */ - -static const struct header_ops cycx_header_ops = { - .create = cycx_netdevice_hard_header, - .rebuild = cycx_netdevice_rebuild_header, -}; - -/* Initialize Linux network interface. - * - * This routine is called only once for each interface, during Linux network - * interface registration. Returning anything but zero will fail interface - * registration. */ -static int cycx_netdevice_init(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - struct cycx_device *card = chan->card; - struct wan_device *wandev = &card->wandev; - - /* Initialize device driver entry points */ - dev->open = cycx_netdevice_open; - dev->stop = cycx_netdevice_stop; - dev->header_ops = &cycx_header_ops; - - dev->hard_start_xmit = cycx_netdevice_hard_start_xmit; - dev->get_stats = cycx_netdevice_get_stats; - - /* Initialize media-specific parameters */ - dev->mtu = CYCX_X25_CHAN_MTU; - dev->type = ARPHRD_HWX25; /* ARP h/w type */ - dev->hard_header_len = 0; /* media header length */ - dev->addr_len = 0; /* hardware address length */ - - if (!chan->svc) - *(__be16*)dev->dev_addr = htons(chan->lcn); - - /* Initialize hardware parameters (just for reference) */ - dev->irq = wandev->irq; - dev->dma = wandev->dma; - dev->base_addr = wandev->ioport; - dev->mem_start = (unsigned long)wandev->maddr; - dev->mem_end = (unsigned long)(wandev->maddr + - wandev->msize - 1); - dev->flags |= IFF_NOARP; - - /* Set transmit buffer queue length */ - dev->tx_queue_len = 10; - - /* Initialize socket buffers */ - cycx_x25_set_chan_state(dev, WAN_DISCONNECTED); - - return 0; -} - -/* Open network interface. - * o prevent module from unloading by incrementing use count - * o if link is disconnected then initiate connection - * - * Return 0 if O.k. or errno. */ -static int cycx_netdevice_open(struct net_device *dev) -{ - if (netif_running(dev)) - return -EBUSY; /* only one open is allowed */ - - netif_start_queue(dev); - return 0; -} - -/* Close network interface. - * o reset flags. - * o if there's no more open channels then disconnect physical link. */ -static int cycx_netdevice_stop(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - - netif_stop_queue(dev); - - if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING) - cycx_x25_chan_disconnect(dev); - - return 0; -} - -/* Build media header. - * o encapsulate packet according to encapsulation type. - * - * The trick here is to put packet type (Ethertype) into 'protocol' field of - * the socket buffer, so that we don't forget it. If encapsulation fails, - * set skb->protocol to 0 and discard packet later. - * - * Return: media header length. */ -static int cycx_netdevice_hard_header(struct sk_buff *skb, - struct net_device *dev, u16 type, - const void *daddr, const void *saddr, - unsigned len) -{ - skb->protocol = htons(type); - - return dev->hard_header_len; -} - -/* * Re-build media header. - * Return: 1 physical address resolved. - * 0 physical address not resolved */ -static int cycx_netdevice_rebuild_header(struct sk_buff *skb) -{ - return 1; -} - -/* Send a packet on a network interface. - * o set busy flag (marks start of the transmission). - * o check link state. If link is not up, then drop the packet. - * o check channel status. If it's down then initiate a call. - * o pass a packet to corresponding WAN device. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * 2. Setting tbusy flag will inhibit further transmit requests from the - * protocol stack and can be used for flow control with protocol layer. */ -static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - struct cycx_device *card = chan->card; - - if (!chan->svc) - chan->protocol = ntohs(skb->protocol); - - if (card->wandev.state != WAN_CONNECTED) - ++chan->ifstats.tx_dropped; - else if (chan->svc && chan->protocol && - chan->protocol != ntohs(skb->protocol)) { - printk(KERN_INFO - "%s: unsupported Ethertype 0x%04X on interface %s!\n", - card->devname, ntohs(skb->protocol), dev->name); - ++chan->ifstats.tx_errors; - } else if (chan->protocol == ETH_P_IP) { - switch (chan->state) { - case WAN_DISCONNECTED: - if (cycx_x25_chan_connect(dev)) { - netif_stop_queue(dev); - return -EBUSY; - } - /* fall thru */ - case WAN_CONNECTED: - reset_timer(dev); - dev->trans_start = jiffies; - netif_stop_queue(dev); - - if (cycx_x25_chan_send(dev, skb)) - return -EBUSY; - - break; - default: - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - } - } else { /* chan->protocol == ETH_P_X25 */ - switch (skb->data[0]) { - case 0: break; - case 1: /* Connect request */ - cycx_x25_chan_connect(dev); - goto free_packet; - case 2: /* Disconnect request */ - cycx_x25_chan_disconnect(dev); - goto free_packet; - default: - printk(KERN_INFO - "%s: unknown %d x25-iface request on %s!\n", - card->devname, skb->data[0], dev->name); - ++chan->ifstats.tx_errors; - goto free_packet; - } - - skb_pull(skb, 1); /* Remove control byte */ - reset_timer(dev); - dev->trans_start = jiffies; - netif_stop_queue(dev); - - if (cycx_x25_chan_send(dev, skb)) { - /* prepare for future retransmissions */ - skb_push(skb, 1); - return -EBUSY; - } - } - -free_packet: - dev_kfree_skb(skb); - - return 0; -} - -/* Get Ethernet-style interface statistics. - * Return a pointer to struct net_device_stats */ -static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - - return chan ? &chan->ifstats : NULL; -} - -/* Interrupt Handlers */ -/* X.25 Interrupt Service Routine. */ -static void cycx_x25_irq_handler(struct cycx_device *card) -{ - struct cycx_x25_cmd cmd; - u16 z = 0; - - card->in_isr = 1; - card->buff_int_mode_unbusy = 0; - cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd)); - - switch (cmd.command) { - case X25_DATA_INDICATION: - cycx_x25_irq_rx(card, &cmd); - break; - case X25_ACK_FROM_VC: - cycx_x25_irq_tx(card, &cmd); - break; - case X25_LOG: - cycx_x25_irq_log(card, &cmd); - break; - case X25_STATISTIC: - cycx_x25_irq_stat(card, &cmd); - break; - case X25_CONNECT_CONFIRM: - cycx_x25_irq_connect_confirm(card, &cmd); - break; - case X25_CONNECT_INDICATION: - cycx_x25_irq_connect(card, &cmd); - break; - case X25_DISCONNECT_INDICATION: - cycx_x25_irq_disconnect(card, &cmd); - break; - case X25_DISCONNECT_CONFIRM: - cycx_x25_irq_disconnect_confirm(card, &cmd); - break; - case X25_LINE_ON: - cycx_set_state(card, WAN_CONNECTED); - break; - case X25_LINE_OFF: - cycx_set_state(card, WAN_DISCONNECTED); - break; - default: - cycx_x25_irq_spurious(card, &cmd); - break; - } - - cycx_poke(&card->hw, 0, &z, sizeof(z)); - cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z)); - card->in_isr = 0; -} - -/* Transmit interrupt handler. - * o Release socket buffer - * o Clear 'tbusy' flag */ -static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd) -{ - struct net_device *dev; - struct wan_device *wandev = &card->wandev; - u8 lcn; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - - /* unbusy device and then dev_tint(); */ - dev = cycx_x25_get_dev_by_lcn(wandev, lcn); - if (dev) { - card->buff_int_mode_unbusy = 1; - netif_wake_queue(dev); - } else - printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n", - card->devname, lcn); -} - -/* Receive interrupt handler. - * This routine handles fragmented IP packets using M-bit according to the - * RFC1356. - * o map logical channel number to network interface. - * o allocate socket buffer or append received packet to the existing one. - * o if M-bit is reset (i.e. it's the last packet in a sequence) then - * decapsulate packet and pass socket buffer to the protocol stack. - * - * Notes: - * 1. When allocating a socket buffer, if M-bit is set then more data is - * coming and we have to allocate buffer for the maximum IP packet size - * expected on this channel. - * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no - * socket buffers available) the whole packet sequence must be discarded. */ -static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd) -{ - struct wan_device *wandev = &card->wandev; - struct net_device *dev; - struct cycx_x25_channel *chan; - struct sk_buff *skb; - u8 bitm, lcn; - int pktlen = cmd->len - 5; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm)); - bitm &= 0x10; - - dev = cycx_x25_get_dev_by_lcn(wandev, lcn); - if (!dev) { - /* Invalid channel, discard packet */ - printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n", - card->devname, lcn); - return; - } - - chan = dev->priv; - reset_timer(dev); - - if (chan->drop_sequence) { - if (!bitm) - chan->drop_sequence = 0; - else - return; - } - - if ((skb = chan->rx_skb) == NULL) { - /* Allocate new socket buffer */ - int bufsize = bitm ? dev->mtu : pktlen; - - if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) + - bufsize + - dev->hard_header_len)) == NULL) { - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - chan->drop_sequence = 1; - ++chan->ifstats.rx_dropped; - return; - } - - if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */ - /* 0 = data packet (dev_alloc_skb zeroed skb->data) */ - skb_put(skb, 1); - - skb->dev = dev; - skb->protocol = htons(chan->protocol); - chan->rx_skb = skb; - } - - if (skb_tailroom(skb) < pktlen) { - /* No room for the packet. Call off the whole thing! */ - dev_kfree_skb_irq(skb); - chan->rx_skb = NULL; - - if (bitm) - chan->drop_sequence = 1; - - printk(KERN_INFO "%s: unexpectedly long packet sequence " - "on interface %s!\n", card->devname, dev->name); - ++chan->ifstats.rx_length_errors; - return; - } - - /* Append packet to the socket buffer */ - cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen); - - if (bitm) - return; /* more data is coming */ - - chan->rx_skb = NULL; /* dequeue packet */ - - ++chan->ifstats.rx_packets; - chan->ifstats.rx_bytes += pktlen; - - skb_reset_mac_header(skb); - netif_rx(skb); - dev->last_rx = jiffies; /* timestamp */ -} - -/* Connect interrupt handler. */ -static void cycx_x25_irq_connect(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - struct wan_device *wandev = &card->wandev; - struct net_device *dev = NULL; - struct cycx_x25_channel *chan; - u8 d[32], - loc[24], - rem[24]; - u8 lcn, sizeloc, sizerem; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc)); - cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6); - - sizerem = sizeloc >> 4; - sizeloc &= 0x0F; - - loc[0] = rem[0] = '\0'; - - if (sizeloc) - nibble_to_byte(d, loc, sizeloc, 0); - - if (sizerem) - nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1); - - dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n", - __FUNCTION__, lcn, loc, rem); - - dev = cycx_x25_get_dev_by_dte_addr(wandev, rem); - if (!dev) { - /* Invalid channel, discard packet */ - printk(KERN_INFO "%s: connect not expected: remote %s!\n", - card->devname, rem); - return; - } - - chan = dev->priv; - chan->lcn = lcn; - cycx_x25_connect_response(card, chan); - cycx_x25_set_chan_state(dev, WAN_CONNECTED); -} - -/* Connect confirm interrupt handler. */ -static void cycx_x25_irq_connect_confirm(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - struct wan_device *wandev = &card->wandev; - struct net_device *dev; - struct cycx_x25_channel *chan; - u8 lcn, key; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key)); - dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n", - card->devname, __FUNCTION__, lcn, key); - - dev = cycx_x25_get_dev_by_lcn(wandev, -key); - if (!dev) { - /* Invalid channel, discard packet */ - clear_bit(--key, (void*)&card->u.x.connection_keys); - printk(KERN_INFO "%s: connect confirm not expected: lcn %d, " - "key=%d!\n", card->devname, lcn, key); - return; - } - - clear_bit(--key, (void*)&card->u.x.connection_keys); - chan = dev->priv; - chan->lcn = lcn; - cycx_x25_set_chan_state(dev, WAN_CONNECTED); -} - -/* Disconnect confirm interrupt handler. */ -static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - struct wan_device *wandev = &card->wandev; - struct net_device *dev; - u8 lcn; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - dprintk(1, KERN_INFO "%s: %s:lcn=%d\n", - card->devname, __FUNCTION__, lcn); - dev = cycx_x25_get_dev_by_lcn(wandev, lcn); - if (!dev) { - /* Invalid channel, discard packet */ - printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n", - card->devname, lcn); - return; - } - - cycx_x25_set_chan_state(dev, WAN_DISCONNECTED); -} - -/* disconnect interrupt handler. */ -static void cycx_x25_irq_disconnect(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - struct wan_device *wandev = &card->wandev; - struct net_device *dev; - u8 lcn; - - cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn); - - dev = cycx_x25_get_dev_by_lcn(wandev, lcn); - if (dev) { - struct cycx_x25_channel *chan = dev->priv; - - cycx_x25_disconnect_response(card, chan->link, lcn); - cycx_x25_set_chan_state(dev, WAN_DISCONNECTED); - } else - cycx_x25_disconnect_response(card, 0, lcn); -} - -/* LOG interrupt handler. */ -static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd) -{ -#if CYCLOMX_X25_DEBUG - char bf[20]; - u16 size, toread, link, msg_code; - u8 code, routine; - - cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code)); - cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link)); - cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size)); - /* at most 20 bytes are available... thanks to Daniela :) */ - toread = size < 20 ? size : 20; - cycx_peek(&card->hw, cmd->buf + 10, &bf, toread); - cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1); - cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1); - - printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n"); - printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf); - printk(KERN_INFO "Log message code=0x%X\n", msg_code); - printk(KERN_INFO "Link=%d\n", link); - printk(KERN_INFO "log code=0x%X\n", code); - printk(KERN_INFO "log routine=0x%X\n", routine); - printk(KERN_INFO "Message size=%d\n", size); - hex_dump("Message", bf, toread); -#endif -} - -/* STATISTIC interrupt handler. */ -static void cycx_x25_irq_stat(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - cycx_peek(&card->hw, cmd->buf, &card->u.x.stats, - sizeof(card->u.x.stats)); - hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats, - sizeof(card->u.x.stats)); - cycx_x25_dump_stats(&card->u.x.stats); - wake_up_interruptible(&card->wait_stats); -} - -/* Spurious interrupt handler. - * o print a warning - * If number of spurious interrupts exceeded some limit, then ??? */ -static void cycx_x25_irq_spurious(struct cycx_device *card, - struct cycx_x25_cmd *cmd) -{ - printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n", - card->devname, cmd->command); -} -#ifdef CYCLOMX_X25_DEBUG -static void hex_dump(char *msg, unsigned char *p, int len) -{ - unsigned char hex[1024], - * phex = hex; - - if (len >= (sizeof(hex) / 2)) - len = (sizeof(hex) / 2) - 1; - - while (len--) { - sprintf(phex, "%02x", *p++); - phex += 2; - } - - printk(KERN_INFO "%s: %s\n", msg, hex); -} -#endif - -/* Cyclom 2X Firmware-Specific Functions */ -/* Exec X.25 command. */ -static int x25_exec(struct cycx_device *card, int command, int link, - void *d1, int len1, void *d2, int len2) -{ - struct cycx_x25_cmd c; - unsigned long flags; - u32 addr = 0x1200 + 0x2E0 * link + 0x1E2; - u8 retry = CYCX_X25_MAX_CMD_RETRY; - int err = 0; - - c.command = command; - c.link = link; - c.len = len1 + len2; - - spin_lock_irqsave(&card->u.x.lock, flags); - - /* write command */ - cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf)); - - /* write X.25 data */ - if (d1) { - cycx_poke(&card->hw, addr, d1, len1); - - if (d2) { - if (len2 > 254) { - u32 addr1 = 0xA00 + 0x400 * link; - - cycx_poke(&card->hw, addr + len1, d2, 249); - cycx_poke(&card->hw, addr1, ((u8*)d2) + 249, - len2 - 249); - } else - cycx_poke(&card->hw, addr + len1, d2, len2); - } - } - - /* generate interruption, executing command */ - cycx_intr(&card->hw); - - /* wait till card->mbox == 0 */ - do { - err = cycx_exec(card->mbox); - } while (retry-- && err); - - spin_unlock_irqrestore(&card->u.x.lock, flags); - - return err; -} - -/* Configure adapter. */ -static int cycx_x25_configure(struct cycx_device *card, - struct cycx_x25_config *conf) -{ - struct { - u16 nlinks; - struct cycx_x25_config conf[2]; - } x25_cmd_conf; - - memset(&x25_cmd_conf, 0, sizeof(x25_cmd_conf)); - x25_cmd_conf.nlinks = 2; - x25_cmd_conf.conf[0] = *conf; - /* FIXME: we need to find a way in the wanrouter framework - to configure the second link, for now lets use it - with the same config from the first link, fixing - the interface type to RS232, the speed in 38400 and - the clock to external */ - x25_cmd_conf.conf[1] = *conf; - x25_cmd_conf.conf[1].link = 1; - x25_cmd_conf.conf[1].speed = 5; /* 38400 */ - x25_cmd_conf.conf[1].clock = 8; - x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */ - - cycx_x25_dump_config(&x25_cmd_conf.conf[0]); - cycx_x25_dump_config(&x25_cmd_conf.conf[1]); - - return x25_exec(card, X25_CONFIG, 0, - &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0); -} - -/* Get protocol statistics. */ -static int cycx_x25_get_stats(struct cycx_device *card) -{ - /* the firmware expects 20 in the size field!!! - thanks to Daniela */ - int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0); - - if (err) - return err; - - interruptible_sleep_on(&card->wait_stats); - - if (signal_pending(current)) - return -EINTR; - - card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames; - card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors; - card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors; - card->wandev.stats.rx_length_errors = 0; /* not available from fw */ - card->wandev.stats.rx_frame_errors = 0; /* not available from fw */ - card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts; - card->wandev.stats.rx_dropped = 0; /* not available from fw */ - card->wandev.stats.rx_errors = 0; /* not available from fw */ - card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames; - card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts; - card->wandev.stats.tx_dropped = 0; /* not available from fw */ - card->wandev.stats.collisions = 0; /* not available from fw */ - card->wandev.stats.tx_errors = 0; /* not available from fw */ - - cycx_x25_dump_devs(&card->wandev); - - return 0; -} - -/* return the number of nibbles */ -static int byte_to_nibble(u8 *s, u8 *d, char *nibble) -{ - int i = 0; - - if (*nibble && *s) { - d[i] |= *s++ - '0'; - *nibble = 0; - ++i; - } - - while (*s) { - d[i] = (*s - '0') << 4; - if (*(s + 1)) - d[i] |= *(s + 1) - '0'; - else { - *nibble = 1; - break; - } - ++i; - s += 2; - } - - return i; -} - -static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble) -{ - if (nibble) { - *d++ = '0' + (*s++ & 0x0F); - --len; - } - - while (len) { - *d++ = '0' + (*s >> 4); - - if (--len) { - *d++ = '0' + (*s & 0x0F); - --len; - } else break; - - ++s; - } - - *d = '\0'; -} - -/* Place X.25 call. */ -static int x25_place_call(struct cycx_device *card, - struct cycx_x25_channel *chan) -{ - int err = 0, - len; - char d[64], - nibble = 0, - mylen = chan->local_addr ? strlen(chan->local_addr) : 0, - remotelen = strlen(chan->addr); - u8 key; - - if (card->u.x.connection_keys == ~0U) { - printk(KERN_INFO "%s: too many simultaneous connection " - "requests!\n", card->devname); - return -EAGAIN; - } - - key = ffz(card->u.x.connection_keys); - set_bit(key, (void*)&card->u.x.connection_keys); - ++key; - dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key); - memset(d, 0, sizeof(d)); - d[1] = key; /* user key */ - d[2] = 0x10; - d[4] = 0x0B; - - len = byte_to_nibble(chan->addr, d + 6, &nibble); - - if (chan->local_addr) - len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble); - - if (nibble) - ++len; - - d[5] = mylen << 4 | remotelen; - d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */ - - if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link, - &d, 7 + len + 1, NULL, 0)) != 0) - clear_bit(--key, (void*)&card->u.x.connection_keys); - else - chan->lcn = -key; - - return err; -} - -/* Place X.25 CONNECT RESPONSE. */ -static int cycx_x25_connect_response(struct cycx_device *card, - struct cycx_x25_channel *chan) -{ - u8 d[8]; - - memset(d, 0, sizeof(d)); - d[0] = d[3] = chan->lcn; - d[2] = 0x10; - d[4] = 0x0F; - d[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */ - - return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0); -} - -/* Place X.25 DISCONNECT RESPONSE. */ -static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link, - u8 lcn) -{ - char d[5]; - - memset(d, 0, sizeof(d)); - d[0] = d[3] = lcn; - d[2] = 0x10; - d[4] = 0x17; - - return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0); -} - -/* Clear X.25 call. */ -static int x25_clear_call(struct cycx_device *card, u8 link, u8 lcn, u8 cause, - u8 diagn) -{ - u8 d[7]; - - memset(d, 0, sizeof(d)); - d[0] = d[3] = lcn; - d[2] = 0x10; - d[4] = 0x13; - d[5] = cause; - d[6] = diagn; - - return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0); -} - -/* Send X.25 data packet. */ -static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm, - int len, void *buf) -{ - u8 d[] = "?\xFF\x10??"; - - d[0] = d[3] = lcn; - d[4] = bitm; - - return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len); -} - -/* Miscellaneous */ -/* Find network device by its channel number. */ -static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev, - s16 lcn) -{ - struct net_device *dev = wandev->dev; - struct cycx_x25_channel *chan; - - while (dev) { - chan = (struct cycx_x25_channel*)dev->priv; - - if (chan->lcn == lcn) - break; - dev = chan->slave; - } - return dev; -} - -/* Find network device by its remote dte address. */ -static struct net_device * - cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte) -{ - struct net_device *dev = wandev->dev; - struct cycx_x25_channel *chan; - - while (dev) { - chan = (struct cycx_x25_channel*)dev->priv; - - if (!strcmp(chan->addr, dte)) - break; - dev = chan->slave; - } - return dev; -} - -/* Initiate connection on the logical channel. - * o for PVC we just get channel configuration - * o for SVCs place an X.25 call - * - * Return: 0 connected - * >0 connection in progress - * <0 failure */ -static int cycx_x25_chan_connect(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - struct cycx_device *card = chan->card; - - if (chan->svc) { - if (!chan->addr[0]) - return -EINVAL; /* no destination address */ - - dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n", - card->devname, chan->addr); - - if (x25_place_call(card, chan)) - return -EIO; - - cycx_x25_set_chan_state(dev, WAN_CONNECTING); - return 1; - } else - cycx_x25_set_chan_state(dev, WAN_CONNECTED); - - return 0; -} - -/* Disconnect logical channel. - * o if SVC then clear X.25 call */ -static void cycx_x25_chan_disconnect(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - - if (chan->svc) { - x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0); - cycx_x25_set_chan_state(dev, WAN_DISCONNECTING); - } else - cycx_x25_set_chan_state(dev, WAN_DISCONNECTED); -} - -/* Called by kernel timer */ -static void cycx_x25_chan_timer(unsigned long d) -{ - struct net_device *dev = (struct net_device *)d; - struct cycx_x25_channel *chan = dev->priv; - - if (chan->state == WAN_CONNECTED) - cycx_x25_chan_disconnect(dev); - else - printk(KERN_ERR "%s: %s for svc (%s) not connected!\n", - chan->card->devname, __FUNCTION__, dev->name); -} - -/* Set logical channel state. */ -static void cycx_x25_set_chan_state(struct net_device *dev, u8 state) -{ - struct cycx_x25_channel *chan = dev->priv; - struct cycx_device *card = chan->card; - unsigned long flags; - char *string_state = NULL; - - spin_lock_irqsave(&card->lock, flags); - - if (chan->state != state) { - if (chan->svc && chan->state == WAN_CONNECTED) - del_timer(&chan->timer); - - switch (state) { - case WAN_CONNECTED: - string_state = "connected!"; - *(__be16*)dev->dev_addr = htons(chan->lcn); - netif_wake_queue(dev); - reset_timer(dev); - - if (chan->protocol == ETH_P_X25) - cycx_x25_chan_send_event(dev, 1); - - break; - case WAN_CONNECTING: - string_state = "connecting..."; - break; - case WAN_DISCONNECTING: - string_state = "disconnecting..."; - break; - case WAN_DISCONNECTED: - string_state = "disconnected!"; - - if (chan->svc) { - *(unsigned short*)dev->dev_addr = 0; - chan->lcn = 0; - } - - if (chan->protocol == ETH_P_X25) - cycx_x25_chan_send_event(dev, 2); - - netif_wake_queue(dev); - break; - } - - printk(KERN_INFO "%s: interface %s %s\n", card->devname, - dev->name, string_state); - chan->state = state; - } - - spin_unlock_irqrestore(&card->lock, flags); -} - -/* Send packet on a logical channel. - * When this function is called, tx_skb field of the channel data space - * points to the transmit socket buffer. When transmission is complete, - * release socket buffer and reset 'tbusy' flag. - * - * Return: 0 - transmission complete - * 1 - busy - * - * Notes: - * 1. If packet length is greater than MTU for this channel, we'll fragment - * the packet into 'complete sequence' using M-bit. - * 2. When transmission is complete, an event notification should be issued - * to the router. */ -static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb) -{ - struct cycx_x25_channel *chan = dev->priv; - struct cycx_device *card = chan->card; - int bitm = 0; /* final packet */ - unsigned len = skb->len; - - if (skb->len > card->wandev.mtu) { - len = card->wandev.mtu; - bitm = 0x10; /* set M-bit (more data) */ - } - - if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data)) - return 1; - - if (bitm) { - skb_pull(skb, len); - return 1; - } - - ++chan->ifstats.tx_packets; - chan->ifstats.tx_bytes += len; - - return 0; -} - -/* Send event (connection, disconnection, etc) to X.25 socket layer */ - -static void cycx_x25_chan_send_event(struct net_device *dev, u8 event) -{ - struct sk_buff *skb; - unsigned char *ptr; - - if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "%s: out of memory\n", __FUNCTION__); - return; - } - - ptr = skb_put(skb, 1); - *ptr = event; - - skb->protocol = x25_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; /* timestamp */ -} - -/* Convert line speed in bps to a number used by cyclom 2x code. */ -static u8 bps_to_speed_code(u32 bps) -{ - u8 number = 0; /* defaults to the lowest (1200) speed ;> */ - - if (bps >= 512000) number = 8; - else if (bps >= 256000) number = 7; - else if (bps >= 64000) number = 6; - else if (bps >= 38400) number = 5; - else if (bps >= 19200) number = 4; - else if (bps >= 9600) number = 3; - else if (bps >= 4800) number = 2; - else if (bps >= 2400) number = 1; - - return number; -} - -/* log base 2 */ -static u8 cycx_log2(u32 n) -{ - u8 log = 0; - - if (!n) - return 0; - - while (n > 1) { - n >>= 1; - ++log; - } - - return log; -} - -/* Convert decimal string to unsigned integer. - * If len != 0 then only 'len' characters of the string are converted. */ -static unsigned dec_to_uint(u8 *str, int len) -{ - unsigned val = 0; - - if (!len) - len = strlen(str); - - for (; len && isdigit(*str); ++str, --len) - val = (val * 10) + (*str - (unsigned) '0'); - - return val; -} - -static void reset_timer(struct net_device *dev) -{ - struct cycx_x25_channel *chan = dev->priv; - - if (chan->svc) - mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ); -} -#ifdef CYCLOMX_X25_DEBUG -static void cycx_x25_dump_config(struct cycx_x25_config *conf) -{ - printk(KERN_INFO "X.25 configuration\n"); - printk(KERN_INFO "-----------------\n"); - printk(KERN_INFO "link number=%d\n", conf->link); - printk(KERN_INFO "line speed=%d\n", conf->speed); - printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In"); - printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2); - printk(KERN_INFO "level 2 window=%d\n", conf->n2win); - printk(KERN_INFO "level 3 window=%d\n", conf->n3win); - printk(KERN_INFO "# logical channels=%d\n", conf->nvc); - printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen); - printk(KERN_INFO "my address=%d\n", conf->locaddr); - printk(KERN_INFO "remote address=%d\n", conf->remaddr); - printk(KERN_INFO "t1=%d seconds\n", conf->t1); - printk(KERN_INFO "t2=%d seconds\n", conf->t2); - printk(KERN_INFO "t21=%d seconds\n", conf->t21); - printk(KERN_INFO "# PVCs=%d\n", conf->npvc); - printk(KERN_INFO "t23=%d seconds\n", conf->t23); - printk(KERN_INFO "flags=0x%x\n", conf->flags); -} - -static void cycx_x25_dump_stats(struct cycx_x25_stats *stats) -{ - printk(KERN_INFO "X.25 statistics\n"); - printk(KERN_INFO "--------------\n"); - printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors); - printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors); - printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames); - printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames); - printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts); - printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts); - printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets); - printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets); - printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts); - printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts); -} - -static void cycx_x25_dump_devs(struct wan_device *wandev) -{ - struct net_device *dev = wandev->dev; - - printk(KERN_INFO "X.25 dev states\n"); - printk(KERN_INFO "name: addr: txoff: protocol:\n"); - printk(KERN_INFO "---------------------------------------\n"); - - while(dev) { - struct cycx_x25_channel *chan = dev->priv; - - printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n", - chan->name, chan->addr, netif_queue_stopped(dev), - chan->protocol == ETH_P_IP ? "IP" : "X25"); - dev = chan->slave; - } -} - -#endif /* CYCLOMX_X25_DEBUG */ -/* End */ diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 96b232446c0..19f7cb2cdef 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -28,6 +28,8 @@ * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> @@ -48,7 +50,6 @@ #include <net/sock.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/dma.h> #include <asm/uaccess.h> @@ -70,14 +71,11 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev, const void *saddr, unsigned len) { struct frhdr hdr; - struct dlci_local *dlp; unsigned int hlen; char *dest; - dlp = dev->priv; - hdr.control = FRAD_I_UI; - switch(type) + switch (type) { case ETH_P_IP: hdr.IP_NLPID = FRAD_P_IP; @@ -97,24 +95,21 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev, dest = skb_push(skb, hlen); if (!dest) - return(0); + return 0; memcpy(dest, &hdr, hlen); - return(hlen); + return hlen; } static void dlci_receive(struct sk_buff *skb, struct net_device *dev) { - struct dlci_local *dlp; struct frhdr *hdr; int process, header; - dlp = dev->priv; if (!pskb_may_pull(skb, sizeof(*hdr))) { - printk(KERN_NOTICE "%s: invalid data no header\n", - dev->name); - dlp->stats.rx_errors++; + netdev_notice(dev, "invalid data no header\n"); + dev->stats.rx_errors++; kfree_skb(skb); return; } @@ -126,24 +121,29 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) if (hdr->control != FRAD_I_UI) { - printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control); - dlp->stats.rx_errors++; + netdev_notice(dev, "Invalid header flag 0x%02X\n", + hdr->control); + dev->stats.rx_errors++; } else - switch(hdr->IP_NLPID) + switch (hdr->IP_NLPID) { case FRAD_P_PADDING: if (hdr->NLPID != FRAD_P_SNAP) { - printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID); - dlp->stats.rx_errors++; + netdev_notice(dev, "Unsupported NLPID 0x%02X\n", + hdr->NLPID); + dev->stats.rx_errors++; break; } if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0) { - printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]); - dlp->stats.rx_errors++; + netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n", + hdr->OUI[0], + hdr->OUI[1], + hdr->OUI[2]); + dev->stats.rx_errors++; break; } @@ -163,13 +163,15 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) case FRAD_P_SNAP: case FRAD_P_Q933: case FRAD_P_CLNP: - printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad); - dlp->stats.rx_errors++; + netdev_notice(dev, "Unsupported NLPID 0x%02X\n", + hdr->pad); + dev->stats.rx_errors++; break; default: - printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad); - dlp->stats.rx_errors++; + netdev_notice(dev, "Invalid pad byte 0x%02X\n", + hdr->pad); + dev->stats.rx_errors++; break; } @@ -178,54 +180,21 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) /* we've set up the protocol, so discard the header */ skb_reset_mac_header(skb); skb_pull(skb, header); - dlp->stats.rx_bytes += skb->len; + dev->stats.rx_bytes += skb->len; netif_rx(skb); - dlp->stats.rx_packets++; - dev->last_rx = jiffies; + dev->stats.rx_packets++; } else dev_kfree_skb(skb); } -static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t dlci_transmit(struct sk_buff *skb, struct net_device *dev) { - struct dlci_local *dlp; - int ret; - - ret = 0; - - if (!skb || !dev) - return(0); - - dlp = dev->priv; - - netif_stop_queue(dev); - - ret = dlp->slave->hard_start_xmit(skb, dlp->slave); - switch (ret) - { - case DLCI_RET_OK: - dlp->stats.tx_packets++; - ret = 0; - break; - case DLCI_RET_ERR: - dlp->stats.tx_errors++; - ret = 0; - break; - case DLCI_RET_DROP: - dlp->stats.tx_dropped++; - ret = 1; - break; - } - /* Alan Cox recommends always returning 0, and always freeing the packet */ - /* experience suggest a slightly more conservative approach */ + struct dlci_local *dlp = netdev_priv(dev); - if (!ret) - { - dev_kfree_skb(skb); - netif_wake_queue(dev); - } - return(ret); + if (skb) + dlp->slave->netdev_ops->ndo_start_xmit(skb, dlp->slave); + return NETDEV_TX_OK; } static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, int get) @@ -235,31 +204,31 @@ static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, in struct frad_local *flp; int err; - dlp = dev->priv; + dlp = netdev_priv(dev); - flp = dlp->slave->priv; + flp = netdev_priv(dlp->slave); if (!get) { - if(copy_from_user(&config, conf, sizeof(struct dlci_conf))) + if (copy_from_user(&config, conf, sizeof(struct dlci_conf))) return -EFAULT; if (config.flags & ~DLCI_VALID_FLAGS) - return(-EINVAL); + return -EINVAL; memcpy(&dlp->config, &config, sizeof(struct dlci_conf)); dlp->configured = 1; } err = (*flp->dlci_conf)(dlp->slave, dev, get); if (err) - return(err); + return err; if (get) { - if(copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf))) + if (copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf))) return -EFAULT; } - return(0); + return 0; } static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -267,15 +236,15 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct dlci_local *dlp; if (!capable(CAP_NET_ADMIN)) - return(-EPERM); + return -EPERM; - dlp = dev->priv; + dlp = netdev_priv(dev); - switch(cmd) + switch (cmd) { case DLCI_GET_SLAVE: if (!*(short *)(dev->dev_addr)) - return(-EINVAL); + return -EINVAL; strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave)); break; @@ -283,24 +252,22 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case DLCI_GET_CONF: case DLCI_SET_CONF: if (!*(short *)(dev->dev_addr)) - return(-EINVAL); + return -EINVAL; - return(dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF)); + return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF); break; default: - return(-EOPNOTSUPP); + return -EOPNOTSUPP; } - return(0); + return 0; } static int dlci_change_mtu(struct net_device *dev, int new_mtu) { - struct dlci_local *dlp; - - dlp = dev->priv; + struct dlci_local *dlp = netdev_priv(dev); - return((*dlp->slave->change_mtu)(dlp->slave, new_mtu)); + return dev_set_mtu(dlp->slave, new_mtu); } static int dlci_open(struct net_device *dev) @@ -309,18 +276,18 @@ static int dlci_open(struct net_device *dev) struct frad_local *flp; int err; - dlp = dev->priv; + dlp = netdev_priv(dev); if (!*(short *)(dev->dev_addr)) - return(-EINVAL); + return -EINVAL; if (!netif_running(dlp->slave)) - return(-ENOTCONN); + return -ENOTCONN; - flp = dlp->slave->priv; + flp = netdev_priv(dlp->slave); err = (*flp->activate)(dlp->slave, dev); if (err) - return(err); + return err; netif_start_queue(dev); @@ -335,23 +302,14 @@ static int dlci_close(struct net_device *dev) netif_stop_queue(dev); - dlp = dev->priv; + dlp = netdev_priv(dev); - flp = dlp->slave->priv; + flp = netdev_priv(dlp->slave); err = (*flp->deactivate)(dlp->slave, dev); return 0; } -static struct net_device_stats *dlci_get_stats(struct net_device *dev) -{ - struct dlci_local *dlp; - - dlp = dev->priv; - - return(&dlp->stats); -} - static int dlci_add(struct dlci_add *dlci) { struct net_device *master, *slave; @@ -365,7 +323,7 @@ static int dlci_add(struct dlci_add *dlci) if (!slave) return -ENODEV; - if (slave->type != ARPHRD_FRAD || slave->priv == NULL) + if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL) goto err1; /* create device name */ @@ -385,17 +343,13 @@ static int dlci_add(struct dlci_add *dlci) } } - err = dev_alloc_name(master, master->name); - if (err < 0) - goto err2; - *(short *)(master->dev_addr) = dlci->dlci; - dlp = (struct dlci_local *) master->priv; + dlp = netdev_priv(master); dlp->slave = slave; dlp->master = master; - flp = slave->priv; + flp = netdev_priv(slave); err = (*flp->assoc)(slave, master); if (err < 0) goto err2; @@ -409,14 +363,14 @@ static int dlci_add(struct dlci_add *dlci) list_add(&dlp->list, &dlci_devs); rtnl_unlock(); - return(0); + return 0; err2: rtnl_unlock(); free_netdev(master); err1: dev_put(slave); - return(err); + return err; } static int dlci_del(struct dlci_add *dlci) @@ -425,21 +379,37 @@ static int dlci_del(struct dlci_add *dlci) struct frad_local *flp; struct net_device *master, *slave; int err; + bool found = false; + + rtnl_lock(); /* validate slave device */ master = __dev_get_by_name(&init_net, dlci->devname); - if (!master) - return(-ENODEV); + if (!master) { + err = -ENODEV; + goto out; + } + + list_for_each_entry(dlp, &dlci_devs, list) { + if (dlp->master == master) { + found = true; + break; + } + } + if (!found) { + err = -ENODEV; + goto out; + } if (netif_running(master)) { - return(-EBUSY); + err = -EBUSY; + goto out; } - dlp = master->priv; + dlp = netdev_priv(master); slave = dlp->slave; - flp = slave->priv; + flp = netdev_priv(slave); - rtnl_lock(); err = (*flp->deassoc)(slave, master); if (!err) { list_del(&dlp->list); @@ -448,9 +418,9 @@ static int dlci_del(struct dlci_add *dlci) dev_put(slave); } +out: rtnl_unlock(); - - return(err); + return err; } static int dlci_ioctl(unsigned int cmd, void __user *arg) @@ -459,9 +429,9 @@ static int dlci_ioctl(unsigned int cmd, void __user *arg) int err; if (!capable(CAP_NET_ADMIN)) - return(-EPERM); + return -EPERM; - if(copy_from_user(&add, arg, sizeof(struct dlci_add))) + if (copy_from_user(&add, arg, sizeof(struct dlci_add))) return -EFAULT; switch (cmd) @@ -470,7 +440,7 @@ static int dlci_ioctl(unsigned int cmd, void __user *arg) err = dlci_add(&add); if (!err) - if(copy_to_user(arg, &add, sizeof(struct dlci_add))) + if (copy_to_user(arg, &add, sizeof(struct dlci_add))) return -EFAULT; break; @@ -482,25 +452,28 @@ static int dlci_ioctl(unsigned int cmd, void __user *arg) err = -EINVAL; } - return(err); + return err; } static const struct header_ops dlci_header_ops = { .create = dlci_header, }; +static const struct net_device_ops dlci_netdev_ops = { + .ndo_open = dlci_open, + .ndo_stop = dlci_close, + .ndo_do_ioctl = dlci_dev_ioctl, + .ndo_start_xmit = dlci_transmit, + .ndo_change_mtu = dlci_change_mtu, +}; + static void dlci_setup(struct net_device *dev) { - struct dlci_local *dlp = dev->priv; + struct dlci_local *dlp = netdev_priv(dev); dev->flags = 0; - dev->open = dlci_open; - dev->stop = dlci_close; - dev->do_ioctl = dlci_dev_ioctl; - dev->hard_start_xmit = dlci_transmit; dev->header_ops = &dlci_header_ops; - dev->get_stats = dlci_get_stats; - dev->change_mtu = dlci_change_mtu; + dev->netdev_ops = &dlci_netdev_ops; dev->destructor = free_netdev; dlp->receive = dlci_receive; @@ -515,9 +488,9 @@ static void dlci_setup(struct net_device *dev) static int dlci_dev_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *) ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); - if (dev->nd_net != &init_net) + if (dev_net(dev) != &init_net) return NOTIFY_DONE; if (event == NETDEV_UNREGISTER) { diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index c6f26e28e37..288610df205 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -56,7 +56,7 @@ * IV. Notes * The current error (XDU, RFO) recovery code is untested. * So far, RDO takes his RX channel down and the right sequence to enable it - * again is still a mistery. If RDO happens, plan a reboot. More details + * again is still a mystery. If RDO happens, plan a reboot. More details * in the code (NB: as this happens, TX still works). * Don't mess the cables during operation, especially on DTE ports. I don't * suggest it for DCE either but at least one can get some messages instead @@ -80,7 +80,10 @@ * - misc crapectomy. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> +#include <linux/sched.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/list.h> @@ -88,8 +91,8 @@ #include <linux/pci.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/slab.h> -#include <asm/system.h> #include <asm/cache.h> #include <asm/byteorder.h> #include <asm/uaccess.h> @@ -97,13 +100,13 @@ #include <asm/irq.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/string.h> #include <linux/if_arp.h> #include <linux/netdevice.h> #include <linux/skbuff.h> #include <linux/delay.h> -#include <net/syncppp.h> #include <linux/hdlc.h> #include <linux/mutex.h> @@ -124,7 +127,7 @@ static u32 dscc4_pci_config_store[16]; /* Module parameters */ MODULE_AUTHOR("Maintainer: Francois Romieu <romieu@cogenit.fr>"); -MODULE_DESCRIPTION("Siemens PEB20534 PCI Controler"); +MODULE_DESCRIPTION("Siemens PEB20534 PCI Controller"); MODULE_LICENSE("GPL"); module_param(debug, int, 0); MODULE_PARM_DESC(debug,"Enable/disable extra messages"); @@ -360,7 +363,8 @@ static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); static int dscc4_found1(struct pci_dev *, void __iomem *ioaddr); static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent); static int dscc4_open(struct net_device *); -static int dscc4_start_xmit(struct sk_buff *, struct net_device *); +static netdev_tx_t dscc4_start_xmit(struct sk_buff *, + struct net_device *); static int dscc4_close(struct net_device *); static int dscc4_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int dscc4_init_ring(struct net_device *); @@ -550,7 +554,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv, schedule_timeout_uninterruptible(10); rmb(); } while (++i > 0); - printk(KERN_ERR "%s: %s timeout\n", dev->name, msg); + netdev_err(dev, "%s timeout\n", msg); done: return (i >= 0) ? i : -EAGAIN; } @@ -566,18 +570,18 @@ static int dscc4_do_action(struct net_device *dev, char *msg) u32 state = readl(ioaddr); if (state & ArAck) { - printk(KERN_DEBUG "%s: %s ack\n", dev->name, msg); + netdev_dbg(dev, "%s ack\n", msg); writel(ArAck, ioaddr); goto done; } else if (state & Arf) { - printk(KERN_ERR "%s: %s failed\n", dev->name, msg); + netdev_err(dev, "%s failed\n", msg); writel(Arf, ioaddr); i = -1; goto done; } rmb(); } while (++i > 0); - printk(KERN_ERR "%s: %s timeout\n", dev->name, msg); + netdev_err(dev, "%s timeout\n", msg); done: return i; } @@ -633,7 +637,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG); if (dscc4_do_action(dev, "Rdt") < 0) - printk(KERN_ERR "%s: Tx reset failed\n", dev->name); + netdev_err(dev, "Tx reset failed\n"); } #endif @@ -642,36 +646,34 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) { struct RxFD *rx_fd = dpriv->rx_fd + dpriv->rx_current%RX_RING_SIZE; - struct net_device_stats *stats = hdlc_stats(dev); struct pci_dev *pdev = dpriv->pci_priv->pdev; struct sk_buff *skb; int pkt_len; skb = dpriv->rx_skbuff[dpriv->rx_current++%RX_RING_SIZE]; if (!skb) { - printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __FUNCTION__); + printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __func__); goto refill; } pkt_len = TO_SIZE(le32_to_cpu(rx_fd->state2)); pci_unmap_single(pdev, le32_to_cpu(rx_fd->data), RX_MAX(HDLC_MAX_MRU), PCI_DMA_FROMDEVICE); if ((skb->data[--pkt_len] & FrameOk) == FrameOk) { - stats->rx_packets++; - stats->rx_bytes += pkt_len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; skb_put(skb, pkt_len); if (netif_running(dev)) skb->protocol = hdlc_type_trans(skb, dev); - skb->dev->last_rx = jiffies; netif_rx(skb); } else { if (skb->data[pkt_len] & FrameRdo) - stats->rx_fifo_errors++; - else if (!(skb->data[pkt_len] | ~FrameCrc)) - stats->rx_crc_errors++; - else if (!(skb->data[pkt_len] | ~(FrameVfr | FrameRab))) - stats->rx_length_errors++; - else - stats->rx_errors++; + dev->stats.rx_fifo_errors++; + else if (!(skb->data[pkt_len] & FrameCrc)) + dev->stats.rx_crc_errors++; + else if ((skb->data[pkt_len] & (FrameVfr | FrameRab)) != + (FrameVfr | FrameRab)) + dev->stats.rx_length_errors++; + dev->stats.rx_errors++; dev_kfree_skb_irq(skb); } refill: @@ -697,16 +699,13 @@ static void dscc4_free1(struct pci_dev *pdev) for (i = 0; i < dev_per_card; i++) unregister_hdlc_device(dscc4_to_dev(root + i)); - pci_set_drvdata(pdev, NULL); - for (i = 0; i < dev_per_card; i++) free_netdev(root[i].dev); kfree(root); kfree(ppriv); } -static int __devinit dscc4_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dscc4_pci_priv *priv; struct dscc4_dev_priv *dpriv; @@ -721,23 +720,20 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, rc = pci_request_region(pdev, 0, "registers"); if (rc < 0) { - printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n", - DRV_NAME); + pr_err("can't reserve MMIO region (regs)\n"); goto err_disable_0; } rc = pci_request_region(pdev, 1, "LBI interface"); if (rc < 0) { - printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n", - DRV_NAME); + pr_err("can't reserve MMIO region (lbi)\n"); goto err_free_mmio_region_1; } - ioaddr = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + ioaddr = pci_ioremap_bar(pdev, 0); if (!ioaddr) { - printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n", - DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0), - (unsigned long long)pci_resource_start(pdev, 0)); + pr_err("cannot remap MMIO region %llx @ %llx\n", + (unsigned long long)pci_resource_len(pdev, 0), + (unsigned long long)pci_resource_start(pdev, 0)); rc = -EIO; goto err_free_mmio_regions_2; } @@ -757,7 +753,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, rc = request_irq(pdev->irq, dscc4_irq, IRQF_SHARED, DRV_NAME, priv->root); if (rc < 0) { - printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq); + pr_warn("IRQ %d busy\n", pdev->irq); goto err_release_4; } @@ -775,14 +771,15 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, } /* Global interrupt queue */ writel((u32)(((IRQ_RING_SIZE >> 5) - 1) << 20), ioaddr + IQLENR1); + + rc = -ENOMEM; + priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(__le32), &priv->iqcfg_dma); if (!priv->iqcfg) goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); - rc = -ENOMEM; - /* * SCC 0-3 private rx/tx irq structures * IQRX/TXi needs to be set soon. Learned it the hard way... @@ -887,6 +884,15 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) return ret; } +static const struct net_device_ops dscc4_ops = { + .ndo_open = dscc4_open, + .ndo_stop = dscc4_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = dscc4_ioctl, + .ndo_tx_timeout = dscc4_tx_timeout, +}; + static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) { struct dscc4_pci_priv *ppriv; @@ -894,10 +900,8 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) int i, ret = -ENOMEM; root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL); - if (!root) { - printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME); + if (!root) goto err_out; - } for (i = 0; i < dev_per_card; i++) { root[i].dev = alloc_hdlcdev(root + i); @@ -906,10 +910,8 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) } ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL); - if (!ppriv) { - printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME); + if (!ppriv) goto err_free_dev; - } ppriv->root = root; spin_lock_init(&ppriv->lock); @@ -920,13 +922,8 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) hdlc_device *hdlc = dev_to_hdlc(d); d->base_addr = (unsigned long)ioaddr; - d->init = NULL; d->irq = pdev->irq; - d->open = dscc4_open; - d->stop = dscc4_close; - d->set_multicast_list = NULL; - d->do_ioctl = dscc4_ioctl; - d->tx_timeout = dscc4_tx_timeout; + d->netdev_ops = &dscc4_ops; d->watchdog_timeo = TX_TIMEOUT; SET_NETDEV_DEV(d, &pdev->dev); @@ -948,7 +945,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) ret = register_hdlc_device(d); if (ret < 0) { - printk(KERN_ERR "%s: unable to register\n", DRV_NAME); + pr_err("unable to register\n"); dscc4_release_ring(dpriv); goto err_unregister; } @@ -1001,7 +998,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv) if (settings->loopback && (settings->clock_type != CLOCK_INT)) { struct net_device *dev = dscc4_to_dev(dpriv); - printk(KERN_INFO "%s: loopback requires clock\n", dev->name); + netdev_info(dev, "loopback requires clock\n"); return -1; } return 0; @@ -1052,7 +1049,7 @@ static int dscc4_open(struct net_device *dev) struct dscc4_pci_priv *ppriv; int ret = -EAGAIN; - if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit) + if ((dscc4_loopback_check(dpriv) < 0)) goto err; if ((ret = hdlc_open(dev))) @@ -1062,7 +1059,7 @@ static int dscc4_open(struct net_device *dev) /* * Due to various bugs, there is no way to reliably reset a - * specific port (manufacturer's dependant special PCI #RST wiring + * specific port (manufacturer's dependent special PCI #RST wiring * apart: it affects all ports). Thus the device goes in the best * silent mode possible at dscc4_close() time and simply claims to * be up if it's opened again. It still isn't possible to change @@ -1074,7 +1071,7 @@ static int dscc4_open(struct net_device *dev) scc_patchl(0, PowerUp, dpriv, dev, CCR0); scc_patchl(0, 0x00050000, dpriv, dev, CCR2); scc_writel(EventsMask, dpriv, dev, IMR); - printk(KERN_INFO "%s: up again.\n", dev->name); + netdev_info(dev, "up again\n"); goto done; } @@ -1091,11 +1088,11 @@ static int dscc4_open(struct net_device *dev) * situations. */ if (scc_readl_star(dpriv, dev) & SccBusy) { - printk(KERN_ERR "%s busy. Try later\n", dev->name); + netdev_err(dev, "busy - try later\n"); ret = -EAGAIN; goto err_out; } else - printk(KERN_INFO "%s: available. Good\n", dev->name); + netdev_info(dev, "available - good\n"); scc_writel(EventsMask, dpriv, dev, IMR); @@ -1113,7 +1110,7 @@ static int dscc4_open(struct net_device *dev) * reset is needed. Suggestions anyone ? */ if ((ret = dscc4_xpr_ack(dpriv)) < 0) { - printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR"); + pr_err("XPR timeout\n"); goto err_disable_scc_events; } @@ -1126,7 +1123,7 @@ done: init_timer(&dpriv->timer); dpriv->timer.expires = jiffies + 10*HZ; dpriv->timer.data = (unsigned long)dev; - dpriv->timer.function = &dscc4_timer; + dpriv->timer.function = dscc4_timer; add_timer(&dpriv->timer); netif_carrier_on(dev); @@ -1148,7 +1145,8 @@ static int dscc4_tx_poll(struct dscc4_dev_priv *dpriv, struct net_device *dev) } #endif /* DSCC4_POLLING */ -static int dscc4_start_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t dscc4_start_xmit(struct sk_buff *skb, + struct net_device *dev) { struct dscc4_dev_priv *dpriv = dscc4_priv(dev); struct dscc4_pci_priv *ppriv = dpriv->pci_priv; @@ -1171,8 +1169,6 @@ static int dscc4_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock(&dpriv->lock); #endif - dev->trans_start = jiffies; - if (debug > 2) dscc4_tx_print(dev, dpriv, "Xmit"); /* To be cleaned(unsigned int)/optimized. Later, ok ? */ @@ -1182,7 +1178,7 @@ static int dscc4_start_xmit(struct sk_buff *skb, struct net_device *dev) if (dscc4_tx_quiescent(dpriv, dev)) dscc4_do_tx(dpriv, dev); - return 0; + return NETDEV_TX_OK; } static int dscc4_close(struct net_device *dev) @@ -1228,9 +1224,9 @@ static inline int dscc4_check_clock_ability(int port) * scaling. Of course some rounding may take place. * - no high speed mode (40Mb/s). May be trivial to do but I don't have an * appropriate external clocking device for testing. - * - no time-slot/clock mode 5: shameless lazyness. + * - no time-slot/clock mode 5: shameless laziness. * - * The clock signals wiring can be (is ?) manufacturer dependant. Good luck. + * The clock signals wiring can be (is ?) manufacturer dependent. Good luck. * * BIG FAT WARNING: if the device isn't provided enough clocking signal, it * won't pass the init sequence. For example, straight back-to-back DTE without @@ -1339,8 +1335,7 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EPERM; if (dpriv->flags & FakeReset) { - printk(KERN_INFO "%s: please reset the device" - " before this command\n", dev->name); + netdev_info(dev, "please reset the device before this command\n"); return -EPERM; } if (copy_from_user(&dpriv->settings, line, size)) @@ -1356,7 +1351,7 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return ret; } -static int dscc4_match(struct thingie *p, int value) +static int dscc4_match(const struct thingie *p, int value) { int i; @@ -1401,7 +1396,7 @@ done: static int dscc4_encoding_setting(struct dscc4_dev_priv *dpriv, struct net_device *dev) { - struct thingie encoding[] = { + static const struct thingie encoding[] = { { ENCODING_NRZ, 0x00000000 }, { ENCODING_NRZI, 0x00200000 }, { ENCODING_FM_MARK, 0x00400000 }, @@ -1440,7 +1435,7 @@ static int dscc4_loopback_setting(struct dscc4_dev_priv *dpriv, static int dscc4_crc_setting(struct dscc4_dev_priv *dpriv, struct net_device *dev) { - struct thingie crc[] = { + static const struct thingie crc[] = { { PARITY_CRC16_PR0_CCITT, 0x00000010 }, { PARITY_CRC16_PR1_CCITT, 0x00000000 }, { PARITY_CRC32_PR0_CCITT, 0x00000011 }, @@ -1503,8 +1498,7 @@ static irqreturn_t dscc4_irq(int irq, void *token) writel(state, ioaddr + GSTAR); if (state & Arf) { - printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n", - dev->name); + netdev_err(dev, "failure (Arf). Harass the maintainer\n"); goto out; } state &= ~ArAck; @@ -1512,7 +1506,7 @@ static irqreturn_t dscc4_irq(int irq, void *token) if (debug > 0) printk(KERN_DEBUG "%s: CfgIV\n", DRV_NAME); if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & cpu_to_le32(Arf)) - printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG"); + netdev_err(dev, "CFG failed\n"); if (!(state &= ~Cfg)) goto out; } @@ -1569,7 +1563,6 @@ try: if (state & SccEvt) { if (state & Alls) { - struct net_device_stats *stats = hdlc_stats(dev); struct sk_buff *skb; struct TxFD *tx_fd; @@ -1586,16 +1579,16 @@ try: pci_unmap_single(ppriv->pdev, le32_to_cpu(tx_fd->data), skb->len, PCI_DMA_TODEVICE); if (tx_fd->state & FrameEnd) { - stats->tx_packets++; - stats->tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; } dev_kfree_skb_irq(skb); dpriv->tx_skbuff[cur] = NULL; ++dpriv->tx_dirty; } else { if (debug > 1) - printk(KERN_ERR "%s Tx: NULL skb %d\n", - dev->name, cur); + netdev_err(dev, "Tx: NULL skb %d\n", + cur); } /* * If the driver ends sending crap on the wire, it @@ -1614,7 +1607,7 @@ try: * Transmit Data Underrun */ if (state & Xdu) { - printk(KERN_ERR "%s: XDU. Ask maintainer\n", DRV_NAME); + netdev_err(dev, "Tx Data Underrun. Ask maintainer\n"); dpriv->flags = NeedIDT; /* Tx reset */ writel(MTFi | Rdt, @@ -1623,13 +1616,13 @@ try: return; } if (state & Cts) { - printk(KERN_INFO "%s: CTS transition\n", dev->name); + netdev_info(dev, "CTS transition\n"); if (!(state &= ~Cts)) /* DEBUG */ goto try; } if (state & Xmr) { /* Frame needs to be sent again - FIXME */ - printk(KERN_ERR "%s: Xmr. Ask maintainer\n", DRV_NAME); + netdev_err(dev, "Tx ReTx. Ask maintainer\n"); if (!(state &= ~Xmr)) /* DEBUG */ goto try; } @@ -1647,7 +1640,7 @@ try: break; } if (!i) - printk(KERN_INFO "%s busy in irq\n", dev->name); + netdev_info(dev, "busy in irq\n"); scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id; /* Keep this order: IDT before IDR */ @@ -1684,7 +1677,7 @@ try: } if (state & Cd) { if (debug > 0) - printk(KERN_INFO "%s: CD transition\n", dev->name); + netdev_info(dev, "CD transition\n"); if (!(state &= ~Cd)) /* DEBUG */ goto try; } @@ -1693,12 +1686,12 @@ try: #ifdef DSCC4_POLLING while (!dscc4_tx_poll(dpriv, dev)); #endif - printk(KERN_INFO "%s: Tx Hi\n", dev->name); + netdev_info(dev, "Tx Hi\n"); state &= ~Hi; } if (state & Err) { - printk(KERN_INFO "%s: Tx ERR\n", dev->name); - hdlc_stats(dev)->tx_errors++; + netdev_info(dev, "Tx ERR\n"); + dev->stats.tx_errors++; state &= ~Err; } } @@ -1767,7 +1760,7 @@ try: goto try; } if (state & Hi ) { /* HI bit */ - printk(KERN_INFO "%s: Rx Hi\n", dev->name); + netdev_info(dev, "Rx Hi\n"); state &= ~Hi; goto try; } @@ -1798,7 +1791,7 @@ try: goto try; } if (state & Cts) { - printk(KERN_INFO "%s: CTS transition\n", dev->name); + netdev_info(dev, "CTS transition\n"); if (!(state &= ~Cts)) /* DEBUG */ goto try; } @@ -1834,7 +1827,7 @@ try: if (!(rx_fd->state2 & DataComplete)) break; if (rx_fd->state2 & FrameAborted) { - hdlc_stats(dev)->rx_over_errors++; + dev->stats.rx_over_errors++; rx_fd->state1 |= Hold; rx_fd->state2 = 0x00000000; rx_fd->end = cpu_to_le32(0xbabeface); @@ -1857,14 +1850,12 @@ try: sizeof(struct RxFD), scc_addr + CH0BRDA); writel(MTFi|Rdr|Idr, scc_addr + CH0CFG); if (dscc4_do_action(dev, "RDR") < 0) { - printk(KERN_ERR "%s: RDO recovery failed(%s)\n", - dev->name, "RDR"); + netdev_err(dev, "RDO recovery failed(RDR)\n"); goto rdo_end; } writel(MTFi|Idr, scc_addr + CH0CFG); if (dscc4_do_action(dev, "IDR") < 0) { - printk(KERN_ERR "%s: RDO recovery failed(%s)\n", - dev->name, "IDR"); + netdev_err(dev, "RDO recovery failed(IDR)\n"); goto rdo_end; } rdo_end: @@ -1873,7 +1864,7 @@ try: goto try; } if (state & Cd) { - printk(KERN_INFO "%s: CD transition\n", dev->name); + netdev_info(dev, "CD transition\n"); if (!(state &= ~Cd)) /* DEBUG */ goto try; } @@ -1974,7 +1965,7 @@ err_out: return -ENOMEM; } -static void __devexit dscc4_remove_one(struct pci_dev *pdev) +static void dscc4_remove_one(struct pci_dev *pdev) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; @@ -2048,7 +2039,7 @@ static int __init dscc4_setup(char *str) __setup("dscc4.setup=", dscc4_setup); #endif -static struct pci_device_id dscc4_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(dscc4_pci_tbl) = { { PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} @@ -2059,18 +2050,7 @@ static struct pci_driver dscc4_driver = { .name = DRV_NAME, .id_table = dscc4_pci_tbl, .probe = dscc4_init_one, - .remove = __devexit_p(dscc4_remove_one), + .remove = dscc4_remove_one, }; -static int __init dscc4_init_module(void) -{ - return pci_register_driver(&dscc4_driver); -} - -static void __exit dscc4_cleanup_module(void) -{ - pci_unregister_driver(&dscc4_driver); -} - -module_init(dscc4_init_module); -module_exit(dscc4_cleanup_module); +module_pci_driver(dscc4_driver); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 547368e9633..1f041271f7f 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -15,12 +15,18 @@ * Maintainer: Kevin Curtis <kevin.curtis@farsite.co.uk> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/version.h> #include <linux/pci.h> +#include <linux/sched.h> +#include <linux/slab.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/delay.h> #include <linux/if.h> #include <linux/hdlc.h> #include <asm/io.h> @@ -47,10 +53,7 @@ MODULE_LICENSE("GPL"); /* Default parameters for the link */ #define FST_TX_QUEUE_LEN 100 /* At 8Mbps a longer queue length is - * useful, the syncppp module forces - * this down assuming a slower line I - * guess. - */ + * useful */ #define FST_TXQ_DEPTH 16 /* This one is for the buffering * of frames on the way down to the card * so that we can keep the card busy @@ -72,7 +75,7 @@ MODULE_LICENSE("GPL"); #endif /* - * Modules parameters and associated varaibles + * Modules parameters and associated variables */ static int fst_txq_low = FST_LOW_WATER_MARK; static int fst_txq_high = FST_HIGH_WATER_MARK; @@ -512,25 +515,23 @@ static int fst_debug_mask = { FST_DEBUG }; * support variable numbers of macro parameters. The inverted if prevents us * eating someone else's else clause. */ -#define dbg(F,fmt,A...) if ( ! ( fst_debug_mask & (F))) \ - ; \ - else \ - printk ( KERN_DEBUG FST_NAME ": " fmt, ## A ) - +#define dbg(F, fmt, args...) \ +do { \ + if (fst_debug_mask & (F)) \ + printk(KERN_DEBUG pr_fmt(fmt), ##args); \ +} while (0) #else -#define dbg(X...) /* NOP */ +#define dbg(F, fmt, args...) \ +do { \ + if (0) \ + printk(KERN_DEBUG pr_fmt(fmt), ##args); \ +} while (0) #endif -/* Printing short cuts - */ -#define printk_err(fmt,A...) printk ( KERN_ERR FST_NAME ": " fmt, ## A ) -#define printk_warn(fmt,A...) printk ( KERN_WARNING FST_NAME ": " fmt, ## A ) -#define printk_info(fmt,A...) printk ( KERN_INFO FST_NAME ": " fmt, ## A ) - /* * PCI ID lookup table */ -static struct pci_device_id fst_pci_dev_id[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(fst_pci_dev_id) = { {PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FST_TYPE_T2P}, @@ -597,7 +598,7 @@ fst_q_work_item(u64 * queue, int card_index) * bottom half for the card. Note the limitation of 64 cards. * That ought to be enough */ - mask = 1 << card_index; + mask = (u64)1 << card_index; *queue |= mask; spin_unlock_irqrestore(&fst_work_q_lock, flags); } @@ -678,7 +679,6 @@ static inline void fst_cpureset(struct fst_card_info *card) { unsigned char interrupt_line_register; - unsigned long j = jiffies + 1; unsigned int regval; if (card->family == FST_FAMILY_TXU) { @@ -696,16 +696,12 @@ fst_cpureset(struct fst_card_info *card) /* * We are delaying here to allow the 9054 to reset itself */ - j = jiffies + 1; - while (jiffies < j) - /* Do nothing */ ; + usleep_range(10, 20); outw(0x240f, card->pci_conf + CNTRL_9054 + 2); /* * We are delaying here to allow the 9054 to reload its eeprom */ - j = jiffies + 1; - while (jiffies < j) - /* Do nothing */ ; + usleep_range(10, 20); outw(0x040f, card->pci_conf + CNTRL_9054 + 2); if (pci_write_config_byte @@ -795,25 +791,6 @@ fst_process_rx_status(int rx_status, char *name) */ break; } - - case NET_RX_CN_LOW: - { - dbg(DBG_ASS, "%s: Receive Low Congestion\n", name); - break; - } - - case NET_RX_CN_MOD: - { - dbg(DBG_ASS, "%s: Receive Moderate Congestion\n", name); - break; - } - - case NET_RX_CN_HIGH: - { - dbg(DBG_ASS, "%s: Receive High Congestion\n", name); - break; - } - case NET_RX_DROP: { dbg(DBG_ASS, "%s: Received packet dropped\n", name); @@ -845,7 +822,6 @@ fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, int len, int txpos) { struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); /* * Everything is now set, just tell the card to go @@ -853,8 +829,8 @@ fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, dbg(DBG_TX, "fst_tx_dma_complete\n"); FST_WRB(card, txDescrRing[port->index][txpos].bits, DMA_OWN | TX_STP | TX_ENP); - stats->tx_packets++; - stats->tx_bytes += len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; dev->trans_start = jiffies; } @@ -876,7 +852,6 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, int len, struct sk_buff *skb, int rxp) { struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); int pi; int rx_status; @@ -888,8 +863,8 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN); /* Update stats */ - stats->rx_packets++; - stats->rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; /* Push upstream */ dbg(DBG_RX, "Pushing the frame up the stack\n"); @@ -900,28 +875,26 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, rx_status = netif_rx(skb); fst_process_rx_status(rx_status, port_to_dev(port)->name); if (rx_status == NET_RX_DROP) - stats->rx_dropped++; - dev->last_rx = jiffies; + dev->stats.rx_dropped++; } /* * Receive a frame through the DMA */ static inline void -fst_rx_dma(struct fst_card_info *card, unsigned char *skb, - unsigned char *mem, int len) +fst_rx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len) { /* * This routine will setup the DMA and start it */ - dbg(DBG_RX, "In fst_rx_dma %p %p %d\n", skb, mem, len); + dbg(DBG_RX, "In fst_rx_dma %x %x %d\n", (u32)dma, mem, len); if (card->dmarx_in_progress) { dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n"); } - outl((unsigned long) skb, card->pci_conf + DMAPADR0); /* Copy to here */ - outl((unsigned long) mem, card->pci_conf + DMALADR0); /* from here */ + outl(dma, card->pci_conf + DMAPADR0); /* Copy to here */ + outl(mem, card->pci_conf + DMALADR0); /* from here */ outl(len, card->pci_conf + DMASIZ0); /* for this length */ outl(0x00000000c, card->pci_conf + DMADPR0); /* In this direction */ @@ -936,20 +909,19 @@ fst_rx_dma(struct fst_card_info *card, unsigned char *skb, * Send a frame through the DMA */ static inline void -fst_tx_dma(struct fst_card_info *card, unsigned char *skb, - unsigned char *mem, int len) +fst_tx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len) { /* * This routine will setup the DMA and start it. */ - dbg(DBG_TX, "In fst_tx_dma %p %p %d\n", skb, mem, len); + dbg(DBG_TX, "In fst_tx_dma %x %x %d\n", (u32)dma, mem, len); if (card->dmatx_in_progress) { dbg(DBG_ASS, "In fst_tx_dma while dma in progress\n"); } - outl((unsigned long) skb, card->pci_conf + DMAPADR1); /* Copy from here */ - outl((unsigned long) mem, card->pci_conf + DMALADR1); /* to here */ + outl(dma, card->pci_conf + DMAPADR1); /* Copy from here */ + outl(mem, card->pci_conf + DMALADR1); /* to here */ outl(len, card->pci_conf + DMASIZ1); /* for this length */ outl(0x000000004, card->pci_conf + DMADPR1); /* In this direction */ @@ -984,7 +956,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd) spin_lock_irqsave(&card->card_lock, flags); if (++safety > 2000) { - printk_err("Mailbox safety timeout\n"); + pr_err("Mailbox safety timeout\n"); break; } @@ -1163,29 +1135,28 @@ fst_log_rx_error(struct fst_card_info *card, struct fst_port_info *port, unsigned char dmabits, int rxp, unsigned short len) { struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); - /* + /* * Increment the appropriate error counter */ - stats->rx_errors++; + dev->stats.rx_errors++; if (dmabits & RX_OFLO) { - stats->rx_fifo_errors++; + dev->stats.rx_fifo_errors++; dbg(DBG_ASS, "Rx fifo error on card %d port %d buffer %d\n", card->card_no, port->index, rxp); } if (dmabits & RX_CRC) { - stats->rx_crc_errors++; + dev->stats.rx_crc_errors++; dbg(DBG_ASS, "Rx crc error on card %d port %d\n", card->card_no, port->index); } if (dmabits & RX_FRAM) { - stats->rx_frame_errors++; + dev->stats.rx_frame_errors++; dbg(DBG_ASS, "Rx frame error on card %d port %d\n", card->card_no, port->index); } if (dmabits == (RX_STP | RX_ENP)) { - stats->rx_length_errors++; + dev->stats.rx_length_errors++; dbg(DBG_ASS, "Rx length error (%d) on card %d port %d\n", len, card->card_no, port->index); } @@ -1242,7 +1213,6 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) unsigned short len; struct sk_buff *skb; struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); /* Check we have a buffer to process */ pi = port->index; @@ -1266,8 +1236,8 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) * This seems to happen on the TE1 interface sometimes * so throw the frame away and log the event. */ - printk_err("Frame received with 0 length. Card %d Port %d\n", - card->card_no, port->index); + pr_err("Frame received with 0 length. Card %d Port %d\n", + card->card_no, port->index); /* Return descriptor to card */ FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN); @@ -1291,7 +1261,7 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) if ((skb = dev_alloc_skb(len)) == NULL) { dbg(DBG_RX, "intr_rx: can't allocate buffer\n"); - stats->rx_dropped++; + dev->stats.rx_dropped++; /* Return descriptor to card */ FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN); @@ -1316,8 +1286,8 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN); /* Update stats */ - stats->rx_packets++; - stats->rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; /* Push upstream */ dbg(DBG_RX, "Pushing frame up the stack\n"); @@ -1327,17 +1297,15 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) skb->protocol = hdlc_type_trans(skb, dev); rx_status = netif_rx(skb); fst_process_rx_status(rx_status, port_to_dev(port)->name); - if (rx_status == NET_RX_DROP) { - stats->rx_dropped++; - } - dev->last_rx = jiffies; + if (rx_status == NET_RX_DROP) + dev->stats.rx_dropped++; } else { card->dma_skb_rx = skb; card->dma_port_rx = port; card->dma_len_rx = len; card->dma_rxpos = rxp; - fst_rx_dma(card, (char *) card->rx_dma_handle_card, - (char *) BUF_OFFSET(rxBuffer[pi][rxp][0]), len); + fst_rx_dma(card, card->rx_dma_handle_card, + BUF_OFFSET(rxBuffer[pi][rxp][0]), len); } if (rxp != port->rxpos) { dbg(DBG_ASS, "About to increment rxpos by more than 1\n"); @@ -1361,7 +1329,6 @@ do_bottom_half_tx(struct fst_card_info *card) struct sk_buff *skb; unsigned long flags; struct net_device *dev; - struct net_device_stats *stats; /* * Find a free buffer for the transmit @@ -1373,12 +1340,10 @@ do_bottom_half_tx(struct fst_card_info *card) if (!port->run) continue; - dev = port_to_dev(port); - stats = hdlc_stats(dev); - while (! - (FST_RDB(card, txDescrRing[pi][port->txpos].bits) & - DMA_OWN) - && !(card->dmatx_in_progress)) { + dev = port_to_dev(port); + while (!(FST_RDB(card, txDescrRing[pi][port->txpos].bits) & + DMA_OWN) && + !(card->dmatx_in_progress)) { /* * There doesn't seem to be a txdone event per-se * We seem to have to deduce it, by checking the DMA_OWN @@ -1410,8 +1375,8 @@ do_bottom_half_tx(struct fst_card_info *card) */ FST_WRW(card, txDescrRing[pi][port->txpos].bcnt, cnv_bcnt(skb->len)); - if ((skb->len < FST_MIN_DMA_LEN) - || (card->family == FST_FAMILY_TXP)) { + if ((skb->len < FST_MIN_DMA_LEN) || + (card->family == FST_FAMILY_TXP)) { /* Enqueue the packet with normal io */ memcpy_toio(card->mem + BUF_OFFSET(txBuffer[pi] @@ -1422,8 +1387,8 @@ do_bottom_half_tx(struct fst_card_info *card) txDescrRing[pi][port->txpos]. bits, DMA_OWN | TX_STP | TX_ENP); - stats->tx_packets++; - stats->tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev->trans_start = jiffies; } else { /* Or do it through dma */ @@ -1433,9 +1398,7 @@ do_bottom_half_tx(struct fst_card_info *card) card->dma_len_tx = skb->len; card->dma_txpos = port->txpos; fst_tx_dma(card, - (char *) card-> - tx_dma_handle_card, - (char *) + card->tx_dma_handle_card, BUF_OFFSET(txBuffer[pi] [port->txpos][0]), skb->len); @@ -1516,9 +1479,8 @@ fst_intr(int dummy, void *dev_id) */ dbg(DBG_INTR, "intr: %d %p\n", card->irq, card); if (card->state != FST_RUNNING) { - printk_err - ("Interrupt received for card %d in a non running state (%d)\n", - card->card_no, card->state); + pr_err("Interrupt received for card %d in a non running state (%d)\n", + card->card_no, card->state); /* * It is possible to really be running, i.e. we have re-loaded @@ -1628,8 +1590,8 @@ fst_intr(int dummy, void *dev_id) * always load up the entire packet for DMA. */ dbg(DBG_TX, "Tx underflow port %d\n", port->index); - hdlc_stats(port_to_dev(port))->tx_errors++; - hdlc_stats(port_to_dev(port))->tx_fifo_errors++; + port_to_dev(port)->stats.tx_errors++; + port_to_dev(port)->stats.tx_fifo_errors++; dbg(DBG_ASS, "Tx underflow on card %d port %d\n", card->card_no, port->index); break; @@ -1644,8 +1606,7 @@ fst_intr(int dummy, void *dev_id) break; default: - printk_err("intr: unknown card event %d. ignored\n", - event); + pr_err("intr: unknown card event %d. ignored\n", event); break; } @@ -1667,13 +1628,13 @@ check_started_ok(struct fst_card_info *card) /* Check structure version and end marker */ if (FST_RDW(card, smcVersion) != SMC_VERSION) { - printk_err("Bad shared memory version %d expected %d\n", - FST_RDW(card, smcVersion), SMC_VERSION); + pr_err("Bad shared memory version %d expected %d\n", + FST_RDW(card, smcVersion), SMC_VERSION); card->state = FST_BADVERSION; return; } if (FST_RDL(card, endOfSmcSignature) != END_SIG) { - printk_err("Missing shared memory signature\n"); + pr_err("Missing shared memory signature\n"); card->state = FST_BADVERSION; return; } @@ -1681,11 +1642,11 @@ check_started_ok(struct fst_card_info *card) if ((i = FST_RDB(card, taskStatus)) == 0x01) { card->state = FST_RUNNING; } else if (i == 0xFF) { - printk_err("Firmware initialisation failed. Card halted\n"); + pr_err("Firmware initialisation failed. Card halted\n"); card->state = FST_HALTED; return; } else if (i != 0x00) { - printk_err("Unknown firmware status 0x%x\n", i); + pr_err("Unknown firmware status 0x%x\n", i); card->state = FST_HALTED; return; } @@ -1695,9 +1656,9 @@ check_started_ok(struct fst_card_info *card) * existing firmware etc so we just report it for the moment. */ if (FST_RDL(card, numberOfPorts) != card->nports) { - printk_warn("Port count mismatch on card %d." - " Firmware thinks %d we say %d\n", card->card_no, - FST_RDL(card, numberOfPorts), card->nports); + pr_warn("Port count mismatch on card %d. Firmware thinks %d we say %d\n", + card->card_no, + FST_RDL(card, numberOfPorts), card->nports); } } @@ -2002,6 +1963,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port, } i = port->index; + memset(&sync, 0, sizeof(sync)); sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed); /* Lucky card and linux use same encoding here */ sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == @@ -2061,23 +2023,17 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Sanity check the parameters. We don't support partial writes * when going over the top */ - if (wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE - || wrthdr.size + wrthdr.offset > FST_MEMSIZE) { + if (wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE || + wrthdr.size + wrthdr.offset > FST_MEMSIZE) { return -ENXIO; } /* Now copy the data to the card. */ - buf = kmalloc(wrthdr.size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, - ifr->ifr_data + sizeof (struct fstioc_write), - wrthdr.size)) { - kfree(buf); - return -EFAULT; - } + buf = memdup_user(ifr->ifr_data + sizeof(struct fstioc_write), + wrthdr.size); + if (IS_ERR(buf)) + return PTR_ERR(buf); memcpy_toio(card->mem + wrthdr.offset, buf, wrthdr.size); kfree(buf); @@ -2126,9 +2082,8 @@ fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) */ if (card->state != FST_RUNNING) { - printk_err - ("Attempt to configure card %d in non-running state (%d)\n", - card->card_no, card->state); + pr_err("Attempt to configure card %d in non-running state (%d)\n", + card->card_no, card->state); return -EIO; } if (copy_from_user(&info, ifr->ifr_data, sizeof (info))) { @@ -2240,8 +2195,10 @@ fst_open(struct net_device *dev) if (port->mode != FST_RAW) { err = hdlc_open(dev); - if (err) + if (err) { + module_put(THIS_MODULE); return err; + } } fst_openport(port); @@ -2292,12 +2249,11 @@ fst_tx_timeout(struct net_device *dev) { struct fst_port_info *port; struct fst_card_info *card; - struct net_device_stats *stats = hdlc_stats(dev); port = dev_to_port(dev); card = port->card; - stats->tx_errors++; - stats->tx_aborted_errors++; + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; dbg(DBG_ASS, "Tx timeout card %d port %d\n", card->card_no, port->index); fst_issue_cmd(port, ABORTTX); @@ -2307,12 +2263,11 @@ fst_tx_timeout(struct net_device *dev) port->start = 0; } -static int +static netdev_tx_t fst_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fst_card_info *card; struct fst_port_info *port; - struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; int txq_length; @@ -2323,12 +2278,12 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Drop packet with error if we don't have carrier */ if (!netif_carrier_ok(dev)) { dev_kfree_skb(skb); - stats->tx_errors++; - stats->tx_carrier_errors++; + dev->stats.tx_errors++; + dev->stats.tx_carrier_errors++; dbg(DBG_ASS, "Tried to transmit but no carrier on card %d port %d\n", card->card_no, port->index); - return 0; + return NETDEV_TX_OK; } /* Drop it if it's too big! MTU failure ? */ @@ -2336,8 +2291,8 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev) dbg(DBG_ASS, "Packet too large %d vs %d\n", skb->len, LEN_TX_BUFFER); dev_kfree_skb(skb); - stats->tx_errors++; - return 0; + dev->stats.tx_errors++; + return NETDEV_TX_OK; } /* @@ -2368,10 +2323,10 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev) * This shouldn't have happened but such is life */ dev_kfree_skb(skb); - stats->tx_errors++; + dev->stats.tx_errors++; dbg(DBG_ASS, "Tx queue overflow card %d port %d\n", card->card_no, port->index); - return 0; + return NETDEV_TX_OK; } /* @@ -2388,7 +2343,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev) fst_q_work_item(&fst_work_txq, card->card_no); tasklet_schedule(&fst_tx_task); - return 0; + return NETDEV_TX_OK; } /* @@ -2398,7 +2353,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev) * via a printk and leave the corresponding interface and all that follow * disabled. */ -static char *type_strings[] __devinitdata = { +static char *type_strings[] = { "no hardware", /* Should never be seen */ "FarSync T2P", "FarSync T4P", @@ -2408,7 +2363,7 @@ static char *type_strings[] __devinitdata = { "FarSync TE1" }; -static void __devinit +static int fst_init_card(struct fst_card_info *card) { int i; @@ -2419,46 +2374,50 @@ fst_init_card(struct fst_card_info *card) * we'll have to revise it in some way then. */ for (i = 0; i < card->nports; i++) { - err = register_hdlc_device(card->ports[i].dev); - if (err < 0) { - int j; - printk_err ("Cannot register HDLC device for port %d" - " (errno %d)\n", i, -err ); - for (j = i; j < card->nports; j++) { - free_netdev(card->ports[j].dev); - card->ports[j].dev = NULL; - } - card->nports = i; - break; - } + err = register_hdlc_device(card->ports[i].dev); + if (err < 0) { + pr_err("Cannot register HDLC device for port %d (errno %d)\n", + i, -err); + while (i--) + unregister_hdlc_device(card->ports[i].dev); + return err; + } } - printk_info("%s-%s: %s IRQ%d, %d ports\n", - port_to_dev(&card->ports[0])->name, - port_to_dev(&card->ports[card->nports - 1])->name, - type_strings[card->type], card->irq, card->nports); + pr_info("%s-%s: %s IRQ%d, %d ports\n", + port_to_dev(&card->ports[0])->name, + port_to_dev(&card->ports[card->nports - 1])->name, + type_strings[card->type], card->irq, card->nports); + return 0; } +static const struct net_device_ops fst_ops = { + .ndo_open = fst_open, + .ndo_stop = fst_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = fst_ioctl, + .ndo_tx_timeout = fst_tx_timeout, +}; + /* * Initialise card when detected. * Returns 0 to indicate success, or errno otherwise. */ -static int __devinit +static int fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int firsttime_done = 0; static int no_of_cards_added = 0; struct fst_card_info *card; int err = 0; int i; - if (!firsttime_done) { - printk_info("FarSync WAN driver " FST_USER_VERSION - " (c) 2001-2004 FarSite Communications Ltd.\n"); - firsttime_done = 1; - dbg(DBG_ASS, "The value of debug mask is %x\n", fst_debug_mask); - } - + printk_once(KERN_INFO + pr_fmt("FarSync WAN driver " FST_USER_VERSION + " (c) 2001-2004 FarSite Communications Ltd.\n")); +#if FST_DEBUG + dbg(DBG_ASS, "The value of debug mask is %x\n", fst_debug_mask); +#endif /* * We are going to be clever and allow certain cards not to be * configured. An exclude list can be provided in /etc/modules.conf @@ -2470,33 +2429,27 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ for (i = 0; i < fst_excluded_cards; i++) { if ((pdev->devfn) >> 3 == fst_excluded_list[i]) { - printk_info("FarSync PCI device %d not assigned\n", - (pdev->devfn) >> 3); + pr_info("FarSync PCI device %d not assigned\n", + (pdev->devfn) >> 3); return -EBUSY; } } } /* Allocate driver private data */ - card = kzalloc(sizeof (struct fst_card_info), GFP_KERNEL); - if (card == NULL) { - printk_err("FarSync card found but insufficient memory for" - " driver storage\n"); + card = kzalloc(sizeof(struct fst_card_info), GFP_KERNEL); + if (card == NULL) return -ENOMEM; - } /* Try to enable the device */ if ((err = pci_enable_device(pdev)) != 0) { - printk_err("Failed to enable card. Err %d\n", -err); - kfree(card); - return err; + pr_err("Failed to enable card. Err %d\n", -err); + goto enable_fail; } if ((err = pci_request_regions(pdev, "FarSync")) !=0) { - printk_err("Failed to allocate regions. Err %d\n", -err); - pci_disable_device(pdev); - kfree(card); - return err; + pr_err("Failed to allocate regions. Err %d\n", -err); + goto regions_fail; } /* Get virtual addresses of memory regions */ @@ -2504,30 +2457,22 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) card->phys_mem = pci_resource_start(pdev, 2); card->phys_ctlmem = pci_resource_start(pdev, 3); if ((card->mem = ioremap(card->phys_mem, FST_MEMSIZE)) == NULL) { - printk_err("Physical memory remap failed\n"); - pci_release_regions(pdev); - pci_disable_device(pdev); - kfree(card); - return -ENODEV; + pr_err("Physical memory remap failed\n"); + err = -ENODEV; + goto ioremap_physmem_fail; } if ((card->ctlmem = ioremap(card->phys_ctlmem, 0x10)) == NULL) { - printk_err("Control memory remap failed\n"); - pci_release_regions(pdev); - pci_disable_device(pdev); - kfree(card); - return -ENODEV; + pr_err("Control memory remap failed\n"); + err = -ENODEV; + goto ioremap_ctlmem_fail; } dbg(DBG_PCI, "kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem); /* Register the interrupt handler */ if (request_irq(pdev->irq, fst_intr, IRQF_SHARED, FST_DEV_NAME, card)) { - printk_err("Unable to register interrupt %d\n", card->irq); - pci_release_regions(pdev); - pci_disable_device(pdev); - iounmap(card->ctlmem); - iounmap(card->mem); - kfree(card); - return -ENODEV; + pr_err("Unable to register interrupt %d\n", card->irq); + err = -ENODEV; + goto irq_fail; } /* Record info we need */ @@ -2552,14 +2497,9 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!dev) { while (i--) free_netdev(card->ports[i].dev); - printk_err ("FarSync: out of memory\n"); - free_irq(card->irq, card); - pci_release_regions(pdev); - pci_disable_device(pdev); - iounmap(card->ctlmem); - iounmap(card->mem); - kfree(card); - return -ENODEV; + pr_err("FarSync: out of memory\n"); + err = -ENOMEM; + goto hdlcdev_fail; } card->ports[i].dev = dev; card->ports[i].card = card; @@ -2580,12 +2520,9 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->base_addr = card->pci_conf; dev->irq = card->irq; - dev->tx_queue_len = FST_TX_QUEUE_LEN; - dev->open = fst_open; - dev->stop = fst_close; - dev->do_ioctl = fst_ioctl; - dev->watchdog_timeo = FST_TX_TIMEOUT; - dev->tx_timeout = fst_tx_timeout; + dev->netdev_ops = &fst_ops; + dev->tx_queue_len = FST_TX_QUEUE_LEN; + dev->watchdog_timeo = FST_TX_TIMEOUT; hdlc->attach = fst_attach; hdlc->xmit = fst_start_xmit; } @@ -2608,9 +2545,16 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, card); /* Remainder of card setup */ + if (no_of_cards_added >= FST_MAX_CARDS) { + pr_err("FarSync: too many cards\n"); + err = -ENOMEM; + goto card_array_fail; + } fst_card_array[no_of_cards_added] = card; card->card_no = no_of_cards_added++; /* Record instance and bump it */ - fst_init_card(card); + err = fst_init_card(card); + if (err) + goto init_card_fail; if (card->family == FST_FAMILY_TXU) { /* * Allocate a dma buffer for transmit and receives @@ -2619,36 +2563,53 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_alloc_consistent(card->device, FST_MAX_MTU, &card->rx_dma_handle_card); if (card->rx_dma_handle_host == NULL) { - printk_err("Could not allocate rx dma buffer\n"); - fst_disable_intr(card); - pci_release_regions(pdev); - pci_disable_device(pdev); - iounmap(card->ctlmem); - iounmap(card->mem); - kfree(card); - return -ENOMEM; + pr_err("Could not allocate rx dma buffer\n"); + err = -ENOMEM; + goto rx_dma_fail; } card->tx_dma_handle_host = pci_alloc_consistent(card->device, FST_MAX_MTU, &card->tx_dma_handle_card); if (card->tx_dma_handle_host == NULL) { - printk_err("Could not allocate tx dma buffer\n"); - fst_disable_intr(card); - pci_release_regions(pdev); - pci_disable_device(pdev); - iounmap(card->ctlmem); - iounmap(card->mem); - kfree(card); - return -ENOMEM; + pr_err("Could not allocate tx dma buffer\n"); + err = -ENOMEM; + goto tx_dma_fail; } } return 0; /* Success */ + +tx_dma_fail: + pci_free_consistent(card->device, FST_MAX_MTU, + card->rx_dma_handle_host, + card->rx_dma_handle_card); +rx_dma_fail: + fst_disable_intr(card); + for (i = 0 ; i < card->nports ; i++) + unregister_hdlc_device(card->ports[i].dev); +init_card_fail: + fst_card_array[card->card_no] = NULL; +card_array_fail: + for (i = 0 ; i < card->nports ; i++) + free_netdev(card->ports[i].dev); +hdlcdev_fail: + free_irq(card->irq, card); +irq_fail: + iounmap(card->ctlmem); +ioremap_ctlmem_fail: + iounmap(card->mem); +ioremap_physmem_fail: + pci_release_regions(pdev); +regions_fail: + pci_disable_device(pdev); +enable_fail: + kfree(card); + return err; } /* * Cleanup and close down a card */ -static void __devexit +static void fst_remove_one(struct pci_dev *pdev) { struct fst_card_info *card; @@ -2685,7 +2646,7 @@ static struct pci_driver fst_driver = { .name = FST_NAME, .id_table = fst_pci_dev_id, .probe = fst_add_one, - .remove = __devexit_p(fst_remove_one), + .remove = fst_remove_one, .suspend = NULL, .resume = NULL, }; @@ -2704,7 +2665,7 @@ fst_init(void) static void __exit fst_cleanup_module(void) { - printk_info("FarSync WAN driver unloading\n"); + pr_info("FarSync WAN driver unloading\n"); pci_unregister_driver(&fst_driver); } diff --git a/drivers/net/wan/farsync.h b/drivers/net/wan/farsync.h index d871dafa87a..6b27e7c3d44 100644 --- a/drivers/net/wan/farsync.h +++ b/drivers/net/wan/farsync.h @@ -54,9 +54,6 @@ /* Ioctl call command values - * - * The first three private ioctls are used by the sync-PPP module, - * allowing a little room for expansion we start our numbering at 10. */ #define FSTWRITE (SIOCDEVPRIVATE+10) #define FSTCPURESET (SIOCDEVPRIVATE+11) @@ -202,9 +199,6 @@ struct fstioc_info { #define J1 7 /* "proto" */ -#define FST_HDLC 1 /* Cisco compatible HDLC */ -#define FST_PPP 2 /* Sync PPP */ -#define FST_MONITOR 3 /* Monitor only (raw packet reception) */ #define FST_RAW 4 /* Two way raw packets */ #define FST_GEN_HDLC 5 /* Using "Generic HDLC" module */ diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd64570.c index 8d0a1f2f00e..dc334c85d96 100644 --- a/drivers/net/wan/hd6457x.c +++ b/drivers/net/wan/hd64570.c @@ -1,5 +1,5 @@ /* - * Hitachi SCA HD64570 and HD64572 common driver for Linux + * Hitachi SCA HD64570 driver for Linux * * Copyright (C) 1998-2003 Krzysztof Halasa <khc@pm.waw.pl> * @@ -7,9 +7,7 @@ * under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * - * Sources of information: - * Hitachi HD64570 SCA User's Manual - * Hitachi HD64572 SCA-II User's Manual + * Source of information: Hitachi HD64570 SCA User's Manual * * We use the following SCA memory map: * @@ -26,33 +24,23 @@ * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers (if used) */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/jiffies.h> -#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/errno.h> #include <linux/fcntl.h> -#include <linux/interrupt.h> +#include <linux/hdlc.h> #include <linux/in.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> -#include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/io.h> - +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/skbuff.h> - -#include <linux/hdlc.h> - -#if (!defined (__HD64570_H) && !defined (__HD64572_H)) || \ - (defined (__HD64570_H) && defined (__HD64572_H)) -#error Either hd64570.h or hd64572.h must be included -#endif +#include <linux/string.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include "hd64570.h" #define get_msci(port) (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) #define get_dmac_rx(port) (phy_node(port) ? DMAC1RX_OFFSET : DMAC0RX_OFFSET) @@ -62,16 +50,6 @@ #define SCA_INTR_DMAC_RX(node) (node ? 0x20 : 0x02) #define SCA_INTR_DMAC_TX(node) (node ? 0x40 : 0x04) -#ifdef __HD64570_H /* HD64570 */ -#define sca_outa(value, reg, card) sca_outw(value, reg, card) -#define sca_ina(reg, card) sca_inw(reg, card) -#define writea(value, ptr) writew(value, ptr) - -#else /* HD64572 */ -#define sca_outa(value, reg, card) sca_outl(value, reg, card) -#define sca_ina(reg, card) sca_inl(reg, card) -#define writea(value, ptr) writel(value, ptr) -#endif static inline struct net_device *port_to_dev(port_t *port) { @@ -81,8 +59,6 @@ static inline struct net_device *port_to_dev(port_t *port) static inline int sca_intr_status(card_t *card) { u8 result = 0; - -#ifdef __HD64570_H /* HD64570 */ u8 isr0 = sca_in(ISR0, card); u8 isr1 = sca_in(ISR1, card); @@ -93,18 +69,6 @@ static inline int sca_intr_status(card_t *card) if (isr0 & 0x0F) result |= SCA_INTR_MSCI(0); if (isr0 & 0xF0) result |= SCA_INTR_MSCI(1); -#else /* HD64572 */ - u32 isr0 = sca_inl(ISR0, card); - - if (isr0 & 0x0000000F) result |= SCA_INTR_DMAC_RX(0); - if (isr0 & 0x000000F0) result |= SCA_INTR_DMAC_TX(0); - if (isr0 & 0x00000F00) result |= SCA_INTR_DMAC_RX(1); - if (isr0 & 0x0000F000) result |= SCA_INTR_DMAC_TX(1); - if (isr0 & 0x003E0000) result |= SCA_INTR_MSCI(0); - if (isr0 & 0x3E000000) result |= SCA_INTR_MSCI(1); - -#endif /* HD64570 vs HD64572 */ - if (!(result & SCA_INTR_DMAC_TX(0))) if (sca_in(DSR_TX(0), card) & DSR_EOM) result |= SCA_INTR_DMAC_TX(0); @@ -127,7 +91,6 @@ static inline u16 next_desc(port_t *port, u16 desc, int transmit) } - static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit) { u16 rx_buffs = port_to_card(port)->rx_ring_buffers; @@ -139,28 +102,26 @@ static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit) } - static inline u16 desc_offset(port_t *port, u16 desc, int transmit) { - /* Descriptor offset always fits in 16 bytes */ + /* Descriptor offset always fits in 16 bits */ return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc); } - -static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc, int transmit) +static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc, + int transmit) { #ifdef PAGE0_ALWAYS_MAPPED return (pkt_desc __iomem *)(win0base(port_to_card(port)) - + desc_offset(port, desc, transmit)); + + desc_offset(port, desc, transmit)); #else return (pkt_desc __iomem *)(winbase(port_to_card(port)) - + desc_offset(port, desc, transmit)); + + desc_offset(port, desc, transmit)); #endif } - static inline u32 buffer_offset(port_t *port, u16 desc, int transmit) { return port_to_card(port)->buff_offset + @@ -186,7 +147,7 @@ static inline void sca_set_carrier(port_t *port) } -static void sca_init_sync_port(port_t *port) +static void sca_init_port(port_t *port) { card_t *card = port_to_card(port); int transmit, i; @@ -195,7 +156,7 @@ static void sca_init_sync_port(port_t *port) port->txin = 0; port->txlast = 0; -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) +#ifndef PAGE0_ALWAYS_MAPPED openwin(card, 0); #endif @@ -209,7 +170,7 @@ static void sca_init_sync_port(port_t *port) u16 chain_off = desc_offset(port, i + 1, transmit); u32 buff_off = buffer_offset(port, i, transmit); - writea(chain_off, &desc->cp); + writew(chain_off, &desc->cp); writel(buff_off, &desc->bp); writew(0, &desc->len); writeb(0, &desc->stat); @@ -222,16 +183,14 @@ static void sca_init_sync_port(port_t *port) sca_out(DCR_ABORT, transmit ? DCR_TX(phy_node(port)) : DCR_RX(phy_node(port)), card); -#ifdef __HD64570_H - sca_out(0, dmac + CPB, card); /* pointer base */ -#endif /* current desc addr */ - sca_outa(desc_offset(port, 0, transmit), dmac + CDAL, card); + sca_out(0, dmac + CPB, card); /* pointer base */ + sca_outw(desc_offset(port, 0, transmit), dmac + CDAL, card); if (!transmit) - sca_outa(desc_offset(port, buffs - 1, transmit), + sca_outw(desc_offset(port, buffs - 1, transmit), dmac + EDAL, card); else - sca_outa(desc_offset(port, 0, transmit), dmac + EDAL, + sca_outw(desc_offset(port, 0, transmit), dmac + EDAL, card); /* clear frame end interrupt counter */ @@ -258,7 +217,6 @@ static void sca_init_sync_port(port_t *port) } - #ifdef NEED_SCA_MSCI_INTR /* MSCI interrupt service */ static inline void sca_msci_intr(port_t *port) @@ -271,9 +229,9 @@ static inline void sca_msci_intr(port_t *port) sca_out(stat & (ST1_UDRN | ST1_CDCD), msci + ST1, card); if (stat & ST1_UDRN) { - struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); - stats->tx_errors++; /* TX Underrun error detected */ - stats->tx_fifo_errors++; + /* TX Underrun error detected */ + port_to_dev(port)->stats.tx_errors++; + port_to_dev(port)->stats.tx_fifo_errors++; } if (stat & ST1_CDCD) @@ -282,28 +240,24 @@ static inline void sca_msci_intr(port_t *port) #endif - -static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u16 rxin) +static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, + u16 rxin) { struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); struct sk_buff *skb; u16 len; u32 buff; -#ifndef ALL_PAGES_ALWAYS_MAPPED u32 maxlen; u8 page; -#endif len = readw(&desc->len); skb = dev_alloc_skb(len); if (!skb) { - stats->rx_dropped++; + dev->stats.rx_dropped++; return; } buff = buffer_offset(port, rxin, 0); -#ifndef ALL_PAGES_ALWAYS_MAPPED page = buff / winsize(card); buff = buff % winsize(card); maxlen = winsize(card) - buff; @@ -315,46 +269,43 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u1 openwin(card, page + 1); memcpy_fromio(skb->data + maxlen, winbase(card), len - maxlen); } else -#endif - memcpy_fromio(skb->data, winbase(card) + buff, len); + memcpy_fromio(skb->data, winbase(card) + buff, len); -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) - /* select pkt_desc table page back */ - openwin(card, 0); +#ifndef PAGE0_ALWAYS_MAPPED + openwin(card, 0); /* select pkt_desc table page back */ #endif skb_put(skb, len); #ifdef DEBUG_PKT printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len); debug_frame(skb); #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; - dev->last_rx = jiffies; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } - /* Receive DMA interrupt service */ static inline void sca_rx_intr(port_t *port) { + struct net_device *dev = port_to_dev(port); u16 dmac = get_dmac_rx(port); card_t *card = port_to_card(port); u8 stat = sca_in(DSR_RX(phy_node(port)), card); /* read DMA Status */ - struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); /* Reset DSR status bits */ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, DSR_RX(phy_node(port)), card); if (stat & DSR_BOF) - stats->rx_over_errors++; /* Dropped one or more frames */ + /* Dropped one or more frames */ + dev->stats.rx_over_errors++; while (1) { u32 desc_off = desc_offset(port, port->rxin, 0); pkt_desc __iomem *desc; - u32 cda = sca_ina(dmac + CDAL, card); + u32 cda = sca_inw(dmac + CDAL, card); if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) break; /* No frame received */ @@ -364,19 +315,21 @@ static inline void sca_rx_intr(port_t *port) if (!(stat & ST_RX_EOM)) port->rxpart = 1; /* partial frame received */ else if ((stat & ST_ERROR_MASK) || port->rxpart) { - stats->rx_errors++; - if (stat & ST_RX_OVERRUN) stats->rx_fifo_errors++; + dev->stats.rx_errors++; + if (stat & ST_RX_OVERRUN) + dev->stats.rx_fifo_errors++; else if ((stat & (ST_RX_SHORT | ST_RX_ABORT | ST_RX_RESBIT)) || port->rxpart) - stats->rx_frame_errors++; - else if (stat & ST_RX_CRC) stats->rx_crc_errors++; + dev->stats.rx_frame_errors++; + else if (stat & ST_RX_CRC) + dev->stats.rx_crc_errors++; if (stat & ST_RX_EOM) port->rxpart = 0; /* received last fragment */ } else sca_rx(card, port, desc, port->rxin); /* Set new error descriptor address */ - sca_outa(desc_off, dmac + EDAL, card); + sca_outw(desc_off, dmac + EDAL, card); port->rxin = next_desc(port, port->rxin, 0); } @@ -385,12 +338,10 @@ static inline void sca_rx_intr(port_t *port) } - /* Transmit DMA interrupt service */ static inline void sca_tx_intr(port_t *port) { struct net_device *dev = port_to_dev(port); - struct net_device_stats *stats = hdlc_stats(dev); u16 dmac = get_dmac_tx(port); card_t* card = port_to_card(port); u8 stat; @@ -407,13 +358,13 @@ static inline void sca_tx_intr(port_t *port) pkt_desc __iomem *desc; u32 desc_off = desc_offset(port, port->txlast, 1); - u32 cda = sca_ina(dmac + CDAL, card); + u32 cda = sca_inw(dmac + CDAL, card); if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) break; /* Transmitter is/will_be sending this frame */ desc = desc_address(port, port->txlast, 1); - stats->tx_packets++; - stats->tx_bytes += readw(&desc->len); + dev->stats.tx_packets++; + dev->stats.tx_bytes += readw(&desc->len); writeb(0, &desc->stat); /* Free descriptor */ port->txlast = next_desc(port, port->txlast, 1); } @@ -423,17 +374,13 @@ static inline void sca_tx_intr(port_t *port) } - static irqreturn_t sca_intr(int irq, void* dev_id) { card_t *card = dev_id; int i; u8 stat; int handled = 0; - -#ifndef ALL_PAGES_ALWAYS_MAPPED u8 page = sca_get_page(card); -#endif while((stat = sca_intr_status(card)) != 0) { handled = 1; @@ -452,14 +399,11 @@ static irqreturn_t sca_intr(int irq, void* dev_id) } } -#ifndef ALL_PAGES_ALWAYS_MAPPED openwin(card, page); /* Restore original page */ -#endif return IRQ_RETVAL(handled); } - static void sca_set_port(port_t *port) { card_t* card = port_to_card(port); @@ -497,12 +441,7 @@ static void sca_set_port(port_t *port) port->tmc = tmc; /* baud divisor - time constant*/ -#ifdef __HD64570_H sca_out(port->tmc, msci + TMC, card); -#else - sca_out(port->tmc, msci + TMCR, card); - sca_out(port->tmc, msci + TMCT, card); -#endif /* Set BRG bits */ sca_out(port->rxs, msci + RXS, card); @@ -518,7 +457,6 @@ static void sca_set_port(port_t *port) } - static void sca_open(struct net_device *dev) { port_t *port = dev_to_port(dev); @@ -540,11 +478,7 @@ static void sca_open(struct net_device *dev) switch(port->parity) { case PARITY_CRC16_PR0: md0 = MD0_HDLC | MD0_CRC_16_0; break; case PARITY_CRC16_PR1: md0 = MD0_HDLC | MD0_CRC_16; break; -#ifdef __HD64570_H case PARITY_CRC16_PR0_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU_0; break; -#else - case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break; -#endif case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break; default: md0 = MD0_HDLC | MD0_CRC_NONE; } @@ -554,35 +488,20 @@ static void sca_open(struct net_device *dev) sca_out(0x00, msci + MD1, card); /* no address field check */ sca_out(md2, msci + MD2, card); sca_out(0x7E, msci + IDL, card); /* flag character 0x7E */ -#ifdef __HD64570_H sca_out(CTL_IDLE, msci + CTL, card); -#else - /* Skip the rest of underrun frame */ - sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card); -#endif -#ifdef __HD64570_H /* Allow at least 8 bytes before requesting RX DMA operation */ /* TX with higher priority and possibly with shorter transfers */ sca_out(0x07, msci + RRC, card); /* +1=RXRDY/DMA activation condition*/ sca_out(0x10, msci + TRC0, card); /* = TXRDY/DMA activation condition*/ sca_out(0x14, msci + TRC1, card); /* +1=TXRDY/DMA deactiv condition */ -#else - sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation condition */ - sca_out(0x3C, msci + TFS, card); /* +1 = TX start */ - sca_out(0x38, msci + TCR, card); /* =Critical TX DMA activ condition */ - sca_out(0x38, msci + TNR0, card); /* =TX DMA activation condition */ - sca_out(0x3F, msci + TNR1, card); /* +1=TX DMA deactivation condition*/ -#endif /* We're using the following interrupts: - TXINT (DMAC completed all transmisions, underrun or DCD change) - all DMA interrupts */ - sca_set_carrier(port); -#ifdef __HD64570_H /* MSCI TX INT and RX INT A IRQ enable */ sca_out(IE0_TXINT | IE0_RXINTA, msci + IE0, card); sca_out(IE1_UDRN | IE1_CDCD, msci + IE1, card); @@ -591,21 +510,8 @@ static void sca_open(struct net_device *dev) /* enable DMA IRQ */ sca_out(sca_in(IER1, card) | (phy_node(port) ? 0xF0 : 0x0F), IER1, card); -#else - /* MSCI TXINT and RXINTA interrupt enable */ - sca_outl(IE0_TXINT | IE0_RXINTA | IE0_UDRN | IE0_CDCD, msci + IE0, - card); - /* DMA & MSCI IRQ enable */ - sca_outl(sca_inl(IER0, card) | - (phy_node(port) ? 0x0A006600 : 0x000A0066), IER0, card); -#endif -#ifdef __HD64570_H sca_out(port->tmc, msci + TMC, card); /* Restore registers */ -#else - sca_out(port->tmc, msci + TMCR, card); - sca_out(port->tmc, msci + TMCT, card); -#endif sca_out(port->rxs, msci + RXS, card); sca_out(port->txs, msci + TXS, card); sca_out(CMD_TX_ENABLE, msci + CMD, card); @@ -615,7 +521,6 @@ static void sca_open(struct net_device *dev) } - static void sca_close(struct net_device *dev) { port_t *port = dev_to_port(dev); @@ -623,23 +528,17 @@ static void sca_close(struct net_device *dev) /* reset channel */ sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port)); -#ifdef __HD64570_H /* disable MSCI interrupts */ sca_out(sca_in(IER0, card) & (phy_node(port) ? 0x0F : 0xF0), IER0, card); /* disable DMA interrupts */ sca_out(sca_in(IER1, card) & (phy_node(port) ? 0x0F : 0xF0), IER1, card); -#else - /* disable DMA & MSCI IRQ */ - sca_outl(sca_inl(IER0, card) & - (phy_node(port) ? 0x00FF00FF : 0xFF00FF00), IER0, card); -#endif + netif_stop_queue(dev); } - static int sca_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { @@ -653,11 +552,7 @@ static int sca_attach(struct net_device *dev, unsigned short encoding, if (parity != PARITY_NONE && parity != PARITY_CRC16_PR0 && parity != PARITY_CRC16_PR1 && -#ifdef __HD64570_H parity != PARITY_CRC16_PR0_CCITT && -#else - parity != PARITY_CRC32_PR1_CCITT && -#endif parity != PARITY_CRC16_PR1_CCITT) return -EINVAL; @@ -667,47 +562,40 @@ static int sca_attach(struct net_device *dev, unsigned short encoding, } - #ifdef DEBUG_RINGS static void sca_dump_rings(struct net_device *dev) { port_t *port = dev_to_port(dev); card_t *card = port_to_card(port); u16 cnt; -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) - u8 page; -#endif +#ifndef PAGE0_ALWAYS_MAPPED + u8 page = sca_get_page(card); -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) - page = sca_get_page(card); openwin(card, 0); #endif printk(KERN_DEBUG "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive", - sca_ina(get_dmac_rx(port) + CDAL, card), - sca_ina(get_dmac_rx(port) + EDAL, card), + sca_inw(get_dmac_rx(port) + CDAL, card), + sca_inw(get_dmac_rx(port) + EDAL, card), sca_in(DSR_RX(phy_node(port)), card), port->rxin, - sca_in(DSR_RX(phy_node(port)), card) & DSR_DE?"":"in"); + sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) - printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + pr_cont("\n"); - printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " "last=%u %sactive", - sca_ina(get_dmac_tx(port) + CDAL, card), - sca_ina(get_dmac_tx(port) + EDAL, card), + sca_inw(get_dmac_tx(port) + CDAL, card), + sca_inw(get_dmac_tx(port) + EDAL, card), sca_in(DSR_TX(phy_node(port)), card), port->txin, port->txlast, sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++) - printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat))); - printk("\n"); + pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat))); + pr_cont("\n"); - printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, " - "ST: %02x %02x %02x %02x" -#ifdef __HD64572_H - " %02x" -#endif - ", FST: %02x CST: %02x %02x\n", + printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x," + " FST: %02x CST: %02x %02x\n", sca_in(get_msci(port) + MD0, card), sca_in(get_msci(port) + MD1, card), sca_in(get_msci(port) + MD2, card), @@ -715,52 +603,33 @@ static void sca_dump_rings(struct net_device *dev) sca_in(get_msci(port) + ST1, card), sca_in(get_msci(port) + ST2, card), sca_in(get_msci(port) + ST3, card), -#ifdef __HD64572_H - sca_in(get_msci(port) + ST4, card), -#endif sca_in(get_msci(port) + FST, card), sca_in(get_msci(port) + CST0, card), sca_in(get_msci(port) + CST1, card)); -#ifdef __HD64572_H - printk(KERN_DEBUG "ILAR: %02x ISR: %08x %08x\n", sca_in(ILAR, card), - sca_inl(ISR0, card), sca_inl(ISR1, card)); -#else printk(KERN_DEBUG "ISR: %02x %02x %02x\n", sca_in(ISR0, card), sca_in(ISR1, card), sca_in(ISR2, card)); -#endif -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) +#ifndef PAGE0_ALWAYS_MAPPED openwin(card, page); /* Restore original page */ #endif } #endif /* DEBUG_RINGS */ - -static int sca_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev) { port_t *port = dev_to_port(dev); card_t *card = port_to_card(port); pkt_desc __iomem *desc; u32 buff, len; -#ifndef ALL_PAGES_ALWAYS_MAPPED u8 page; u32 maxlen; -#endif spin_lock_irq(&port->lock); desc = desc_address(port, port->txin + 1, 1); - if (readb(&desc->stat)) { /* allow 1 packet gap */ - /* should never happen - previous xmit should stop queue */ -#ifdef DEBUG_PKT - printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name); -#endif - netif_stop_queue(dev); - spin_unlock_irq(&port->lock); - return 1; /* request packet to be queued */ - } + BUG_ON(readb(&desc->stat)); /* previous xmit should stop queue */ #ifdef DEBUG_PKT printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len); @@ -770,7 +639,6 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) desc = desc_address(port, port->txin, 1); buff = buffer_offset(port, port->txin, 1); len = skb->len; -#ifndef ALL_PAGES_ALWAYS_MAPPED page = buff / winsize(card); buff = buff % winsize(card); maxlen = winsize(card) - buff; @@ -780,20 +648,17 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) memcpy_toio(winbase(card) + buff, skb->data, maxlen); openwin(card, page + 1); memcpy_toio(winbase(card), skb->data + maxlen, len - maxlen); - } - else -#endif + } else memcpy_toio(winbase(card) + buff, skb->data, len); -#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) +#ifndef PAGE0_ALWAYS_MAPPED openwin(card, 0); /* select pkt_desc table page back */ #endif writew(len, &desc->len); writeb(ST_TX_EOM, &desc->stat); - dev->trans_start = jiffies; port->txin = next_desc(port, port->txin, 1); - sca_outa(desc_offset(port, port->txin, 1), + sca_outw(desc_offset(port, port->txin, 1), get_dmac_tx(port) + EDAL, card); sca_out(DSR_DE, DSR_TX(phy_node(port)), card); /* Enable TX DMA */ @@ -805,44 +670,32 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&port->lock); dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } - #ifdef NEED_DETECT_RAM -static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize) +static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize) { /* Round RAM size to 32 bits, fill from end to start */ u32 i = ramsize &= ~3; - -#ifndef ALL_PAGES_ALWAYS_MAPPED u32 size = winsize(card); openwin(card, (i - 4) / size); /* select last window */ -#endif + do { i -= 4; -#ifndef ALL_PAGES_ALWAYS_MAPPED if ((i + 4) % size == 0) openwin(card, i / size); writel(i ^ 0x12345678, rambase + i % size); -#else - writel(i ^ 0x12345678, rambase + i); -#endif - }while (i > 0); + } while (i > 0); for (i = 0; i < ramsize ; i += 4) { -#ifndef ALL_PAGES_ALWAYS_MAPPED if (i % size == 0) openwin(card, i / size); if (readl(rambase + i % size) != (i ^ 0x12345678)) break; -#else - if (readl(rambase + i) != (i ^ 0x12345678)) - break; -#endif } return i; @@ -850,8 +703,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsi #endif /* NEED_DETECT_RAM */ - -static void __devinit sca_init(card_t *card, int wait_states) +static void sca_init(card_t *card, int wait_states) { sca_out(wait_states, WCRL, card); /* Wait Control */ sca_out(wait_states, WCRM, card); diff --git a/drivers/net/wan/hd64570.h b/drivers/net/wan/hd64570.h index 3839662ff20..10963e8f4b3 100644 --- a/drivers/net/wan/hd64570.h +++ b/drivers/net/wan/hd64570.h @@ -153,13 +153,13 @@ typedef struct { u16 len; /* Data Length */ u8 stat; /* Status */ u8 unused; /* pads to 2-byte boundary */ -}__attribute__ ((packed)) pkt_desc; +}__packed pkt_desc; /* Packet Descriptor Status bits */ #define ST_TX_EOM 0x80 /* End of frame */ -#define ST_TX_EOT 0x01 /* End of transmition */ +#define ST_TX_EOT 0x01 /* End of transmission */ #define ST_RX_EOM 0x80 /* End of frame */ #define ST_RX_SHORT 0x40 /* Short frame */ @@ -211,7 +211,7 @@ typedef struct { #define CTL_NORTS 0x01 #define CTL_IDLE 0x10 /* Transmit an idle pattern */ -#define CTL_UDRNC 0x20 /* Idle after CRC or FCS+flag transmition */ +#define CTL_UDRNC 0x20 /* Idle after CRC or FCS+flag transmission */ #define ST0_TXRDY 0x02 /* TX ready */ #define ST0_RXRDY 0x01 /* RX ready */ diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c new file mode 100644 index 00000000000..e92ecf1d331 --- /dev/null +++ b/drivers/net/wan/hd64572.c @@ -0,0 +1,639 @@ +/* + * Hitachi (now Renesas) SCA-II HD64572 driver for Linux + * + * Copyright (C) 1998-2008 Krzysztof Halasa <khc@pm.waw.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * Source of information: HD64572 SCA-II User's Manual + * + * We use the following SCA memory map: + * + * Packet buffer descriptor rings - starting from card->rambase: + * rx_ring_buffers * sizeof(pkt_desc) = logical channel #0 RX ring + * tx_ring_buffers * sizeof(pkt_desc) = logical channel #0 TX ring + * rx_ring_buffers * sizeof(pkt_desc) = logical channel #1 RX ring (if used) + * tx_ring_buffers * sizeof(pkt_desc) = logical channel #1 TX ring (if used) + * + * Packet data buffers - starting from card->rambase + buff_offset: + * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers + * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers + * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers (if used) + * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers (if used) + */ + +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/fcntl.h> +#include <linux/hdlc.h> +#include <linux/in.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/string.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include "hd64572.h" + +#define NAPI_WEIGHT 16 + +#define get_msci(port) (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET) +#define get_dmac_rx(port) (port->chan ? DMAC1RX_OFFSET : DMAC0RX_OFFSET) +#define get_dmac_tx(port) (port->chan ? DMAC1TX_OFFSET : DMAC0TX_OFFSET) + +#define sca_in(reg, card) readb(card->scabase + (reg)) +#define sca_out(value, reg, card) writeb(value, card->scabase + (reg)) +#define sca_inw(reg, card) readw(card->scabase + (reg)) +#define sca_outw(value, reg, card) writew(value, card->scabase + (reg)) +#define sca_inl(reg, card) readl(card->scabase + (reg)) +#define sca_outl(value, reg, card) writel(value, card->scabase + (reg)) + +static int sca_poll(struct napi_struct *napi, int budget); + +static inline port_t* dev_to_port(struct net_device *dev) +{ + return dev_to_hdlc(dev)->priv; +} + +static inline void enable_intr(port_t *port) +{ + /* enable DMIB and MSCI RXINTA interrupts */ + sca_outl(sca_inl(IER0, port->card) | + (port->chan ? 0x08002200 : 0x00080022), IER0, port->card); +} + +static inline void disable_intr(port_t *port) +{ + sca_outl(sca_inl(IER0, port->card) & + (port->chan ? 0x00FF00FF : 0xFF00FF00), IER0, port->card); +} + +static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit) +{ + u16 rx_buffs = port->card->rx_ring_buffers; + u16 tx_buffs = port->card->tx_ring_buffers; + + desc %= (transmit ? tx_buffs : rx_buffs); // called with "X + 1" etc. + return port->chan * (rx_buffs + tx_buffs) + transmit * rx_buffs + desc; +} + + +static inline u16 desc_offset(port_t *port, u16 desc, int transmit) +{ + /* Descriptor offset always fits in 16 bits */ + return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc); +} + + +static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc, + int transmit) +{ + return (pkt_desc __iomem *)(port->card->rambase + + desc_offset(port, desc, transmit)); +} + + +static inline u32 buffer_offset(port_t *port, u16 desc, int transmit) +{ + return port->card->buff_offset + + desc_abs_number(port, desc, transmit) * (u32)HDLC_MAX_MRU; +} + + +static inline void sca_set_carrier(port_t *port) +{ + if (!(sca_in(get_msci(port) + ST3, port->card) & ST3_DCD)) { +#ifdef DEBUG_LINK + printk(KERN_DEBUG "%s: sca_set_carrier on\n", + port->netdev.name); +#endif + netif_carrier_on(port->netdev); + } else { +#ifdef DEBUG_LINK + printk(KERN_DEBUG "%s: sca_set_carrier off\n", + port->netdev.name); +#endif + netif_carrier_off(port->netdev); + } +} + + +static void sca_init_port(port_t *port) +{ + card_t *card = port->card; + u16 dmac_rx = get_dmac_rx(port), dmac_tx = get_dmac_tx(port); + int transmit, i; + + port->rxin = 0; + port->txin = 0; + port->txlast = 0; + + for (transmit = 0; transmit < 2; transmit++) { + u16 buffs = transmit ? card->tx_ring_buffers + : card->rx_ring_buffers; + + for (i = 0; i < buffs; i++) { + pkt_desc __iomem *desc = desc_address(port, i, transmit); + u16 chain_off = desc_offset(port, i + 1, transmit); + u32 buff_off = buffer_offset(port, i, transmit); + + writel(chain_off, &desc->cp); + writel(buff_off, &desc->bp); + writew(0, &desc->len); + writeb(0, &desc->stat); + } + } + + /* DMA disable - to halt state */ + sca_out(0, DSR_RX(port->chan), card); + sca_out(0, DSR_TX(port->chan), card); + + /* software ABORT - to initial state */ + sca_out(DCR_ABORT, DCR_RX(port->chan), card); + sca_out(DCR_ABORT, DCR_TX(port->chan), card); + + /* current desc addr */ + sca_outl(desc_offset(port, 0, 0), dmac_rx + CDAL, card); + sca_outl(desc_offset(port, card->tx_ring_buffers - 1, 0), + dmac_rx + EDAL, card); + sca_outl(desc_offset(port, 0, 1), dmac_tx + CDAL, card); + sca_outl(desc_offset(port, 0, 1), dmac_tx + EDAL, card); + + /* clear frame end interrupt counter */ + sca_out(DCR_CLEAR_EOF, DCR_RX(port->chan), card); + sca_out(DCR_CLEAR_EOF, DCR_TX(port->chan), card); + + /* Receive */ + sca_outw(HDLC_MAX_MRU, dmac_rx + BFLL, card); /* set buffer length */ + sca_out(0x14, DMR_RX(port->chan), card); /* Chain mode, Multi-frame */ + sca_out(DIR_EOME, DIR_RX(port->chan), card); /* enable interrupts */ + sca_out(DSR_DE, DSR_RX(port->chan), card); /* DMA enable */ + + /* Transmit */ + sca_out(0x14, DMR_TX(port->chan), card); /* Chain mode, Multi-frame */ + sca_out(DIR_EOME, DIR_TX(port->chan), card); /* enable interrupts */ + + sca_set_carrier(port); + netif_napi_add(port->netdev, &port->napi, sca_poll, NAPI_WEIGHT); +} + + +/* MSCI interrupt service */ +static inline void sca_msci_intr(port_t *port) +{ + u16 msci = get_msci(port); + card_t* card = port->card; + + if (sca_in(msci + ST1, card) & ST1_CDCD) { + /* Reset MSCI CDCD status bit */ + sca_out(ST1_CDCD, msci + ST1, card); + sca_set_carrier(port); + } +} + + +static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, + u16 rxin) +{ + struct net_device *dev = port->netdev; + struct sk_buff *skb; + u16 len; + u32 buff; + + len = readw(&desc->len); + skb = dev_alloc_skb(len); + if (!skb) { + dev->stats.rx_dropped++; + return; + } + + buff = buffer_offset(port, rxin, 0); + memcpy_fromio(skb->data, card->rambase + buff, len); + + skb_put(skb, len); +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len); + debug_frame(skb); +#endif + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + skb->protocol = hdlc_type_trans(skb, dev); + netif_receive_skb(skb); +} + + +/* Receive DMA service */ +static inline int sca_rx_done(port_t *port, int budget) +{ + struct net_device *dev = port->netdev; + u16 dmac = get_dmac_rx(port); + card_t *card = port->card; + u8 stat = sca_in(DSR_RX(port->chan), card); /* read DMA Status */ + int received = 0; + + /* Reset DSR status bits */ + sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, + DSR_RX(port->chan), card); + + if (stat & DSR_BOF) + /* Dropped one or more frames */ + dev->stats.rx_over_errors++; + + while (received < budget) { + u32 desc_off = desc_offset(port, port->rxin, 0); + pkt_desc __iomem *desc; + u32 cda = sca_inl(dmac + CDAL, card); + + if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) + break; /* No frame received */ + + desc = desc_address(port, port->rxin, 0); + stat = readb(&desc->stat); + if (!(stat & ST_RX_EOM)) + port->rxpart = 1; /* partial frame received */ + else if ((stat & ST_ERROR_MASK) || port->rxpart) { + dev->stats.rx_errors++; + if (stat & ST_RX_OVERRUN) + dev->stats.rx_fifo_errors++; + else if ((stat & (ST_RX_SHORT | ST_RX_ABORT | + ST_RX_RESBIT)) || port->rxpart) + dev->stats.rx_frame_errors++; + else if (stat & ST_RX_CRC) + dev->stats.rx_crc_errors++; + if (stat & ST_RX_EOM) + port->rxpart = 0; /* received last fragment */ + } else { + sca_rx(card, port, desc, port->rxin); + received++; + } + + /* Set new error descriptor address */ + sca_outl(desc_off, dmac + EDAL, card); + port->rxin = (port->rxin + 1) % card->rx_ring_buffers; + } + + /* make sure RX DMA is enabled */ + sca_out(DSR_DE, DSR_RX(port->chan), card); + return received; +} + + +/* Transmit DMA service */ +static inline void sca_tx_done(port_t *port) +{ + struct net_device *dev = port->netdev; + card_t* card = port->card; + u8 stat; + unsigned count = 0; + + spin_lock(&port->lock); + + stat = sca_in(DSR_TX(port->chan), card); /* read DMA Status */ + + /* Reset DSR status bits */ + sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, + DSR_TX(port->chan), card); + + while (1) { + pkt_desc __iomem *desc = desc_address(port, port->txlast, 1); + u8 stat = readb(&desc->stat); + + if (!(stat & ST_TX_OWNRSHP)) + break; /* not yet transmitted */ + if (stat & ST_TX_UNDRRUN) { + dev->stats.tx_errors++; + dev->stats.tx_fifo_errors++; + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += readw(&desc->len); + } + writeb(0, &desc->stat); /* Free descriptor */ + count++; + port->txlast = (port->txlast + 1) % card->tx_ring_buffers; + } + + if (count) + netif_wake_queue(dev); + spin_unlock(&port->lock); +} + + +static int sca_poll(struct napi_struct *napi, int budget) +{ + port_t *port = container_of(napi, port_t, napi); + u32 isr0 = sca_inl(ISR0, port->card); + int received = 0; + + if (isr0 & (port->chan ? 0x08000000 : 0x00080000)) + sca_msci_intr(port); + + if (isr0 & (port->chan ? 0x00002000 : 0x00000020)) + sca_tx_done(port); + + if (isr0 & (port->chan ? 0x00000200 : 0x00000002)) + received = sca_rx_done(port, budget); + + if (received < budget) { + napi_complete(napi); + enable_intr(port); + } + + return received; +} + +static irqreturn_t sca_intr(int irq, void *dev_id) +{ + card_t *card = dev_id; + u32 isr0 = sca_inl(ISR0, card); + int i, handled = 0; + + for (i = 0; i < 2; i++) { + port_t *port = get_port(card, i); + if (port && (isr0 & (i ? 0x08002200 : 0x00080022))) { + handled = 1; + disable_intr(port); + napi_schedule(&port->napi); + } + } + + return IRQ_RETVAL(handled); +} + + +static void sca_set_port(port_t *port) +{ + card_t* card = port->card; + u16 msci = get_msci(port); + u8 md2 = sca_in(msci + MD2, card); + unsigned int tmc, br = 10, brv = 1024; + + + if (port->settings.clock_rate > 0) { + /* Try lower br for better accuracy*/ + do { + br--; + brv >>= 1; /* brv = 2^9 = 512 max in specs */ + + /* Baud Rate = CLOCK_BASE / TMC / 2^BR */ + tmc = CLOCK_BASE / brv / port->settings.clock_rate; + }while (br > 1 && tmc <= 128); + + if (tmc < 1) { + tmc = 1; + br = 0; /* For baud=CLOCK_BASE we use tmc=1 br=0 */ + brv = 1; + } else if (tmc > 255) + tmc = 256; /* tmc=0 means 256 - low baud rates */ + + port->settings.clock_rate = CLOCK_BASE / brv / tmc; + } else { + br = 9; /* Minimum clock rate */ + tmc = 256; /* 8bit = 0 */ + port->settings.clock_rate = CLOCK_BASE / (256 * 512); + } + + port->rxs = (port->rxs & ~CLK_BRG_MASK) | br; + port->txs = (port->txs & ~CLK_BRG_MASK) | br; + port->tmc = tmc; + + /* baud divisor - time constant*/ + sca_out(port->tmc, msci + TMCR, card); + sca_out(port->tmc, msci + TMCT, card); + + /* Set BRG bits */ + sca_out(port->rxs, msci + RXS, card); + sca_out(port->txs, msci + TXS, card); + + if (port->settings.loopback) + md2 |= MD2_LOOPBACK; + else + md2 &= ~MD2_LOOPBACK; + + sca_out(md2, msci + MD2, card); + +} + + +static void sca_open(struct net_device *dev) +{ + port_t *port = dev_to_port(dev); + card_t* card = port->card; + u16 msci = get_msci(port); + u8 md0, md2; + + switch(port->encoding) { + case ENCODING_NRZ: md2 = MD2_NRZ; break; + case ENCODING_NRZI: md2 = MD2_NRZI; break; + case ENCODING_FM_MARK: md2 = MD2_FM_MARK; break; + case ENCODING_FM_SPACE: md2 = MD2_FM_SPACE; break; + default: md2 = MD2_MANCHESTER; + } + + if (port->settings.loopback) + md2 |= MD2_LOOPBACK; + + switch(port->parity) { + case PARITY_CRC16_PR0: md0 = MD0_HDLC | MD0_CRC_16_0; break; + case PARITY_CRC16_PR1: md0 = MD0_HDLC | MD0_CRC_16; break; + case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break; + case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break; + default: md0 = MD0_HDLC | MD0_CRC_NONE; + } + + sca_out(CMD_RESET, msci + CMD, card); + sca_out(md0, msci + MD0, card); + sca_out(0x00, msci + MD1, card); /* no address field check */ + sca_out(md2, msci + MD2, card); + sca_out(0x7E, msci + IDL, card); /* flag character 0x7E */ + /* Skip the rest of underrun frame */ + sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card); + sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation condition */ + sca_out(0x3C, msci + TFS, card); /* +1 = TX start */ + sca_out(0x38, msci + TCR, card); /* =Critical TX DMA activ condition */ + sca_out(0x38, msci + TNR0, card); /* =TX DMA activation condition */ + sca_out(0x3F, msci + TNR1, card); /* +1=TX DMA deactivation condition*/ + +/* We're using the following interrupts: + - RXINTA (DCD changes only) + - DMIB (EOM - single frame transfer complete) +*/ + sca_outl(IE0_RXINTA | IE0_CDCD, msci + IE0, card); + + sca_out(port->tmc, msci + TMCR, card); + sca_out(port->tmc, msci + TMCT, card); + sca_out(port->rxs, msci + RXS, card); + sca_out(port->txs, msci + TXS, card); + sca_out(CMD_TX_ENABLE, msci + CMD, card); + sca_out(CMD_RX_ENABLE, msci + CMD, card); + + sca_set_carrier(port); + enable_intr(port); + napi_enable(&port->napi); + netif_start_queue(dev); +} + + +static void sca_close(struct net_device *dev) +{ + port_t *port = dev_to_port(dev); + + /* reset channel */ + sca_out(CMD_RESET, get_msci(port) + CMD, port->card); + disable_intr(port); + napi_disable(&port->napi); + netif_stop_queue(dev); +} + + +static int sca_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +{ + if (encoding != ENCODING_NRZ && + encoding != ENCODING_NRZI && + encoding != ENCODING_FM_MARK && + encoding != ENCODING_FM_SPACE && + encoding != ENCODING_MANCHESTER) + return -EINVAL; + + if (parity != PARITY_NONE && + parity != PARITY_CRC16_PR0 && + parity != PARITY_CRC16_PR1 && + parity != PARITY_CRC32_PR1_CCITT && + parity != PARITY_CRC16_PR1_CCITT) + return -EINVAL; + + dev_to_port(dev)->encoding = encoding; + dev_to_port(dev)->parity = parity; + return 0; +} + + +#ifdef DEBUG_RINGS +static void sca_dump_rings(struct net_device *dev) +{ + port_t *port = dev_to_port(dev); + card_t *card = port->card; + u16 cnt; + + printk(KERN_DEBUG "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive", + sca_inl(get_dmac_rx(port) + CDAL, card), + sca_inl(get_dmac_rx(port) + EDAL, card), + sca_in(DSR_RX(port->chan), card), port->rxin, + sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in"); + for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++) + pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + pr_cont("\n"); + + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + "last=%u %sactive", + sca_inl(get_dmac_tx(port) + CDAL, card), + sca_inl(get_dmac_tx(port) + EDAL, card), + sca_in(DSR_TX(port->chan), card), port->txin, port->txlast, + sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in"); + + for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++) + pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat))); + pr_cont("\n"); + + printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x," + " ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n", + sca_in(get_msci(port) + MD0, card), + sca_in(get_msci(port) + MD1, card), + sca_in(get_msci(port) + MD2, card), + sca_in(get_msci(port) + ST0, card), + sca_in(get_msci(port) + ST1, card), + sca_in(get_msci(port) + ST2, card), + sca_in(get_msci(port) + ST3, card), + sca_in(get_msci(port) + ST4, card), + sca_in(get_msci(port) + FST, card), + sca_in(get_msci(port) + CST0, card), + sca_in(get_msci(port) + CST1, card)); + + printk(KERN_DEBUG "ILAR: %02x ISR: %08x %08x\n", sca_in(ILAR, card), + sca_inl(ISR0, card), sca_inl(ISR1, card)); +} +#endif /* DEBUG_RINGS */ + + +static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev) +{ + port_t *port = dev_to_port(dev); + card_t *card = port->card; + pkt_desc __iomem *desc; + u32 buff, len; + + spin_lock_irq(&port->lock); + + desc = desc_address(port, port->txin + 1, 1); + BUG_ON(readb(&desc->stat)); /* previous xmit should stop queue */ + +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len); + debug_frame(skb); +#endif + + desc = desc_address(port, port->txin, 1); + buff = buffer_offset(port, port->txin, 1); + len = skb->len; + memcpy_toio(card->rambase + buff, skb->data, len); + + writew(len, &desc->len); + writeb(ST_TX_EOM, &desc->stat); + + port->txin = (port->txin + 1) % card->tx_ring_buffers; + sca_outl(desc_offset(port, port->txin, 1), + get_dmac_tx(port) + EDAL, card); + + sca_out(DSR_DE, DSR_TX(port->chan), card); /* Enable TX DMA */ + + desc = desc_address(port, port->txin + 1, 1); + if (readb(&desc->stat)) /* allow 1 packet gap */ + netif_stop_queue(dev); + + spin_unlock_irq(&port->lock); + + dev_kfree_skb(skb); + return NETDEV_TX_OK; +} + + +static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize) +{ + /* Round RAM size to 32 bits, fill from end to start */ + u32 i = ramsize &= ~3; + + do { + i -= 4; + writel(i ^ 0x12345678, rambase + i); + } while (i > 0); + + for (i = 0; i < ramsize ; i += 4) { + if (readl(rambase + i) != (i ^ 0x12345678)) + break; + } + + return i; +} + + +static void sca_init(card_t *card, int wait_states) +{ + sca_out(wait_states, WCRL, card); /* Wait Control */ + sca_out(wait_states, WCRM, card); + sca_out(wait_states, WCRH, card); + + sca_out(0, DMER, card); /* DMA Master disable */ + sca_out(0x03, PCR, card); /* DMA priority */ + sca_out(0, DSR_RX(0), card); /* DMA disable - to halt state */ + sca_out(0, DSR_TX(0), card); + sca_out(0, DSR_RX(1), card); + sca_out(0, DSR_TX(1), card); + sca_out(DMER_DME, DMER, card); /* DMA Master enable */ +} diff --git a/drivers/net/wan/hd64572.h b/drivers/net/wan/hd64572.h index 96567c2dc4d..22137ee669c 100644 --- a/drivers/net/wan/hd64572.h +++ b/drivers/net/wan/hd64572.h @@ -218,7 +218,7 @@ typedef struct { #define ST_TX_EOM 0x80 /* End of frame */ #define ST_TX_UNDRRUN 0x08 #define ST_TX_OWNRSHP 0x02 -#define ST_TX_EOT 0x01 /* End of transmition */ +#define ST_TX_EOT 0x01 /* End of transmission */ #define ST_RX_EOM 0x80 /* End of frame */ #define ST_RX_SHORT 0x40 /* Short frame */ diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 39951d0c34d..9c33ca918e1 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -22,20 +22,21 @@ * - proto->start() and stop() are called with spin_lock_irq held. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/errno.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/notifier.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/notifier.h> -#include <linux/hdlc.h> +#include <linux/skbuff.h> +#include <linux/slab.h> #include <net/net_namespace.h> @@ -43,10 +44,9 @@ static const char* version = "HDLC support module revision 1.22"; #undef DEBUG_LINK -static struct hdlc_proto *first_proto = NULL; - +static struct hdlc_proto *first_proto; -static int hdlc_change_mtu(struct net_device *dev, int new_mtu) +int hdlc_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) return -EINVAL; @@ -54,21 +54,12 @@ static int hdlc_change_mtu(struct net_device *dev, int new_mtu) return 0; } - - -static struct net_device_stats *hdlc_get_stats(struct net_device *dev) -{ - return hdlc_stats(dev); -} - - - static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) { struct hdlc_device *hdlc = dev_to_hdlc(dev); - if (dev->nd_net != &init_net) { + if (!net_eq(dev_net(dev), &init_net)) { kfree_skb(skb); return 0; } @@ -77,7 +68,15 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, return hdlc->proto->netif_rx(skb); } +netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + if (hdlc->proto->xmit) + return hdlc->proto->xmit(skb, dev); + + return hdlc->xmit(skb, dev); /* call hardware driver directly */ +} static inline void hdlc_proto_start(struct net_device *dev) { @@ -100,19 +99,19 @@ static inline void hdlc_proto_stop(struct net_device *dev) static int hdlc_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); hdlc_device *hdlc; unsigned long flags; int on; - - if (dev->nd_net != &init_net) + + if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; - if (dev->get_stats != hdlc_get_stats) + if (!(dev->priv_flags & IFF_WAN_HDLC)) return NOTIFY_DONE; /* not an HDLC device */ - + if (event != NETDEV_CHANGE) - return NOTIFY_DONE; /* Only interrested in carrier changes */ + return NOTIFY_DONE; /* Only interested in carrier changes */ on = netif_carrier_ok(dev); @@ -133,10 +132,10 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event, goto carrier_exit; if (hdlc->carrier) { - printk(KERN_INFO "%s: Carrier detected\n", dev->name); + netdev_info(dev, "Carrier detected\n"); hdlc_proto_start(dev); } else { - printk(KERN_INFO "%s: Carrier lost\n", dev->name); + netdev_info(dev, "Carrier lost\n"); hdlc_proto_stop(dev); } @@ -168,10 +167,10 @@ int hdlc_open(struct net_device *dev) spin_lock_irq(&hdlc->state_lock); if (hdlc->carrier) { - printk(KERN_INFO "%s: Carrier detected\n", dev->name); + netdev_info(dev, "Carrier detected\n"); hdlc_proto_start(dev); } else - printk(KERN_INFO "%s: No carrier\n", dev->name); + netdev_info(dev, "No carrier\n"); hdlc->open = 1; @@ -235,15 +234,13 @@ static void hdlc_setup_dev(struct net_device *dev) /* Re-init all variables changed by HDLC protocol drivers, * including ether_setup() called from hdlc_raw_eth.c. */ - dev->get_stats = hdlc_get_stats; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->priv_flags = IFF_WAN_HDLC; dev->mtu = HDLC_MAX_MTU; dev->type = ARPHRD_RAWHDLC; dev->hard_header_len = 16; dev->addr_len = 0; dev->header_ops = &hdlc_null_ops; - - dev->change_mtu = hdlc_change_mtu; } static void hdlc_setup(struct net_device *dev) @@ -283,14 +280,13 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, 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"); + if (size) { + dev_to_hdlc(dev)->state = kmalloc(size, GFP_KERNEL); + if (dev_to_hdlc(dev)->state == NULL) { module_put(proto->module); return -ENOBUFS; } + } dev_to_hdlc(dev)->proto = proto; return 0; } @@ -314,21 +310,25 @@ void detach_hdlc_protocol(struct net_device *dev) void register_hdlc_protocol(struct hdlc_proto *proto) { + rtnl_lock(); proto->next = first_proto; first_proto = proto; + rtnl_unlock(); } void unregister_hdlc_protocol(struct hdlc_proto *proto) { - struct hdlc_proto **p = &first_proto; - while (*p) { - if (*p == proto) { - *p = proto->next; - return; - } + struct hdlc_proto **p; + + rtnl_lock(); + p = &first_proto; + while (*p != proto) { + BUG_ON(!*p); p = &((*p)->next); } + *p = proto->next; + rtnl_unlock(); } @@ -337,6 +337,8 @@ MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); MODULE_DESCRIPTION("HDLC support module"); MODULE_LICENSE("GPL v2"); +EXPORT_SYMBOL(hdlc_change_mtu); +EXPORT_SYMBOL(hdlc_start_xmit); EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_ioctl); @@ -347,14 +349,14 @@ 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), +static struct packet_type hdlc_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_HDLC), .func = hdlc_rcv, }; static struct notifier_block hdlc_notifier = { - .notifier_call = hdlc_device_event, + .notifier_call = hdlc_device_event, }; @@ -362,10 +364,10 @@ static int __init hdlc_module_init(void) { int result; - printk(KERN_INFO "%s\n", version); + pr_info("%s\n", version); if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0) - return result; - dev_add_pack(&hdlc_packet_type); + return result; + dev_add_pack(&hdlc_packet_type); return 0; } diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 7133c688cf2..3f20808b5ff 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -9,19 +9,17 @@ * as published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/hdlc.h> +#include <linux/skbuff.h> #undef DEBUG_HARD_HEADER @@ -38,7 +36,7 @@ struct hdlc_header { u8 address; u8 control; __be16 protocol; -}__attribute__ ((packed)); +}__packed; struct cisco_packet { @@ -47,7 +45,7 @@ struct cisco_packet { __be32 par2; __be16 rel; /* reliability */ __be32 time; -}__attribute__ ((packed)); +}__packed; #define CISCO_PACKET_LEN 18 #define CISCO_BIG_PACKET_LEN 20 @@ -56,10 +54,10 @@ struct cisco_state { cisco_proto settings; struct timer_list timer; + spinlock_t lock; unsigned long last_poll; int up; - int request_sent; - u32 txseq; /* TX sequence number */ + u32 txseq; /* TX sequence number, 0 = none */ u32 rxseq; /* RX sequence number */ }; @@ -67,9 +65,9 @@ struct cisco_state { static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr); -static inline struct cisco_state * state(hdlc_device *hdlc) +static inline struct cisco_state* state(hdlc_device *hdlc) { - return(struct cisco_state *)(hdlc->state); + return (struct cisco_state *)hdlc->state; } @@ -105,9 +103,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, 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", - dev->name); + netdev_warn(dev, "Memory squeeze on cisco_keepalive_send()\n"); return; } skb_reserve(skb, 4); @@ -117,7 +113,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, data->type = htonl(type); data->par1 = par1; data->par2 = par2; - data->rel = __constant_htons(0xFFFF); + data->rel = cpu_to_be16(0xFFFF); /* we will need do_div here if 1000 % HZ != 0 */ data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); @@ -136,20 +132,20 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) struct hdlc_header *data = (struct hdlc_header*)skb->data; if (skb->len < sizeof(struct hdlc_header)) - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); - switch(data->protocol) { - case __constant_htons(ETH_P_IP): - case __constant_htons(ETH_P_IPX): - case __constant_htons(ETH_P_IPV6): + switch (data->protocol) { + case cpu_to_be16(ETH_P_IP): + case cpu_to_be16(ETH_P_IPX): + case cpu_to_be16(ETH_P_IPV6): skb_pull(skb, sizeof(struct hdlc_header)); return data->protocol; default: - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); } } @@ -158,10 +154,12 @@ static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); + struct cisco_state *st = state(hdlc); struct hdlc_header *data = (struct hdlc_header*)skb->data; struct cisco_packet *cisco_data; struct in_device *in_dev; __be32 addr, mask; + u32 ack; if (skb->len < sizeof(struct hdlc_header)) goto rx_error; @@ -170,7 +168,7 @@ static int cisco_rx(struct sk_buff *skb) data->address != CISCO_UNICAST) goto rx_error; - switch(ntohs(data->protocol)) { + switch (ntohs(data->protocol)) { case CISCO_SYS_INFO: /* Packet is not needed, drop it. */ dev_kfree_skb_any(skb); @@ -181,19 +179,20 @@ static int cisco_rx(struct sk_buff *skb) 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); + netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n", + skb->len); goto rx_error; } cisco_data = (struct cisco_packet*)(skb->data + sizeof (struct hdlc_header)); - switch(ntohl (cisco_data->type)) { + switch (ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ - in_dev = dev->ip_ptr; + rcu_read_lock(); + in_dev = __in_dev_get_rcu(dev); addr = 0; - mask = __constant_htonl(~0); /* is the mask correct? */ + mask = ~cpu_to_be32(0); /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; @@ -211,46 +210,47 @@ static int cisco_rx(struct sk_buff *skb) cisco_keepalive_send(dev, CISCO_ADDR_REPLY, addr, mask); } + rcu_read_unlock(); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_ADDR_REPLY: - printk(KERN_INFO "%s: Unexpected Cisco IP address " - "reply\n", dev->name); + netdev_info(dev, "Unexpected Cisco IP address reply\n"); goto rx_error; case CISCO_KEEPALIVE_REQ: - 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) { + spin_lock(&st->lock); + st->rxseq = ntohl(cisco_data->par1); + ack = ntohl(cisco_data->par2); + if (ack && (ack == st->txseq || + /* our current REQ may be in transit */ + ack == st->txseq - 1)) { + st->last_poll = jiffies; + if (!st->up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; - printk(KERN_INFO "%s: Link up (peer " - "uptime %ud%uh%um%us)\n", - dev->name, days, hrs, - min, sec); + netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n", + days, hrs, min, sec); netif_dormant_off(dev); - state(hdlc)->up = 1; + st->up = 1; } } + spin_unlock(&st->lock); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; - } /* switch(keepalive type) */ - } /* switch(protocol) */ + } /* switch (keepalive type) */ + } /* switch (protocol) */ - printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, - ntohs(data->protocol)); + netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol)); dev_kfree_skb_any(skb); return NET_RX_DROP; - rx_error: - dev_to_hdlc(dev)->stats.rx_errors++; /* Mark error */ +rx_error: + dev->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -261,24 +261,24 @@ static void cisco_timer(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; hdlc_device *hdlc = dev_to_hdlc(dev); + struct cisco_state *st = state(hdlc); - 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); + spin_lock(&st->lock); + if (st->up && + time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) { + st->up = 0; + netdev_info(dev, "Link down\n"); netif_dormant_on(dev); } - cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, - htonl(++state(hdlc)->txseq), - htonl(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); + cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq), + htonl(st->rxseq)); + spin_unlock(&st->lock); + + st->timer.expires = jiffies + st->settings.interval * HZ; + st->timer.function = cisco_timer; + st->timer.data = arg; + add_timer(&st->timer); } @@ -286,15 +286,18 @@ static void cisco_timer(unsigned long arg) static void cisco_start(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - 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); + struct cisco_state *st = state(hdlc); + unsigned long flags; + + spin_lock_irqsave(&st->lock, flags); + st->up = st->txseq = st->rxseq = 0; + spin_unlock_irqrestore(&st->lock, flags); + + init_timer(&st->timer); + st->timer.expires = jiffies + HZ; /* First poll after 1 s */ + st->timer.function = cisco_timer; + st->timer.data = (unsigned long)dev; + add_timer(&st->timer); } @@ -302,10 +305,15 @@ 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(&state(hdlc)->timer); + struct cisco_state *st = state(hdlc); + unsigned long flags; + + del_timer_sync(&st->timer); + + spin_lock_irqsave(&st->lock, flags); netif_dormant_on(dev); - state(hdlc)->up = 0; - state(hdlc)->request_sent = 0; + st->up = st->txseq = 0; + spin_unlock_irqrestore(&st->lock, flags); } @@ -321,7 +329,7 @@ static struct hdlc_proto proto = { static const struct header_ops cisco_header_ops = { .create = cisco_hard_header, }; - + static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) { cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; @@ -344,10 +352,10 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; case IF_PROTO_CISCO: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, cisco_s, size)) @@ -357,7 +365,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) new_settings.timeout < 2) return -EINVAL; - result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result = hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; @@ -367,7 +375,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) return result; memcpy(&state(hdlc)->settings, &new_settings, size); - dev->hard_start_xmit = hdlc->xmit; + spin_lock_init(&state(hdlc)->lock); dev->header_ops = &cisco_header_ops; dev->type = ARPHRD_CISCO; netif_dormant_on(dev); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index c4ab0326f91..7c6cb4f3179 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -33,20 +33,19 @@ */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/etherdevice.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/etherdevice.h> -#include <linux/hdlc.h> +#include <linux/skbuff.h> +#include <linux/slab.h> #undef DEBUG_PKT #undef DEBUG_ECN @@ -96,7 +95,7 @@ typedef struct { unsigned ea1: 1; unsigned cr: 1; unsigned dlcih: 6; - + unsigned ea2: 1; unsigned de: 1; unsigned becn: 1; @@ -113,7 +112,7 @@ typedef struct { unsigned de: 1; unsigned ea2: 1; #endif -}__attribute__ ((packed)) fr_hdr; +}__packed fr_hdr; typedef struct pvc_device_struct { @@ -135,11 +134,6 @@ typedef struct pvc_device_struct { }state; }pvc_device; -struct pvc_desc { - struct net_device_stats stats; - pvc_device *pvc; -}; - struct frad_state { fr_proto settings; pvc_device *first_pvc; @@ -179,15 +173,6 @@ static inline struct frad_state* state(hdlc_device *hdlc) return(struct frad_state *)(hdlc->state); } -static inline struct pvc_desc* pvcdev_to_desc(struct net_device *dev) -{ - return dev->priv; -} - -static inline struct net_device_stats* pvc_get_stats(struct net_device *dev) -{ - return &pvcdev_to_desc(dev)->stats; -} static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) { @@ -197,7 +182,7 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) if (pvc->dlci == dlci) return pvc; if (pvc->dlci > dlci) - return NULL; /* the listed is sorted */ + return NULL; /* the list is sorted */ pvc = pvc->next; } @@ -293,31 +278,31 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) struct sk_buff *skb = *skb_p; switch (skb->protocol) { - case __constant_htons(NLPID_CCITT_ANSI_LMI): + case cpu_to_be16(NLPID_CCITT_ANSI_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CCITT_ANSI_LMI; break; - case __constant_htons(NLPID_CISCO_LMI): + case cpu_to_be16(NLPID_CISCO_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CISCO_LMI; break; - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IPV6; break; - case __constant_htons(ETH_P_802_3): + case cpu_to_be16(ETH_P_802_3): head_len = 10; if (skb_headroom(skb) < head_len) { struct sk_buff *skb2 = skb_realloc_headroom(skb, @@ -357,7 +342,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) static int pvc_open(struct net_device *dev) { - pvc_device *pvc = pvcdev_to_desc(dev)->pvc; + pvc_device *pvc = dev->ml_priv; if ((pvc->frad->flags & IFF_UP) == 0) return -EIO; /* Frad must be UP in order to activate PVC */ @@ -377,7 +362,7 @@ static int pvc_open(struct net_device *dev) static int pvc_close(struct net_device *dev) { - pvc_device *pvc = pvcdev_to_desc(dev)->pvc; + pvc_device *pvc = dev->ml_priv; if (--pvc->open_count == 0) { hdlc_device *hdlc = dev_to_hdlc(pvc->frad); @@ -396,7 +381,7 @@ static int pvc_close(struct net_device *dev) static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - pvc_device *pvc = pvcdev_to_desc(dev)->pvc; + pvc_device *pvc = dev->ml_priv; fr_proto_pvc_info info; if (ifr->ifr_settings.type == IF_GET_PROTO) { @@ -422,10 +407,9 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; } -static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev) { - pvc_device *pvc = pvcdev_to_desc(dev)->pvc; - struct net_device_stats *stats = pvc_get_stats(dev); + pvc_device *pvc = dev->ml_priv; if (pvc->state.active) { if (dev->type == ARPHRD_ETHER) { @@ -435,54 +419,41 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_tailroom(skb) < pad) if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { - stats->tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } skb_put(skb, pad); memset(skb->data + len, 0, pad); } - skb->protocol = __constant_htons(ETH_P_802_3); + skb->protocol = cpu_to_be16(ETH_P_802_3); } if (!fr_hard_header(&skb, pvc->dlci)) { - stats->tx_bytes += skb->len; - stats->tx_packets++; + dev->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; if (pvc->state.fecn) /* TX Congestion counter */ - stats->tx_compressed++; + dev->stats.tx_compressed++; skb->dev = pvc->frad; dev_queue_xmit(skb); - return 0; + return NETDEV_TX_OK; } } - stats->tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); - return 0; -} - - - -static int pvc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; + return NETDEV_TX_OK; } - - static inline void fr_log_dlci_active(pvc_device *pvc) { - printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", - pvc->frad->name, - pvc->dlci, - pvc->main ? pvc->main->name : "", - pvc->main && pvc->ether ? " " : "", - pvc->ether ? pvc->ether->name : "", - pvc->state.new ? " new" : "", - !pvc->state.exist ? "deleted" : - pvc->state.active ? "active" : "inactive"); + netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n", + pvc->dlci, + pvc->main ? pvc->main->name : "", + pvc->main && pvc->ether ? " " : "", + pvc->ether ? pvc->ether->name : "", + pvc->state.new ? " new" : "", + !pvc->state.exist ? "deleted" : + pvc->state.active ? "active" : "inactive"); } @@ -509,25 +480,23 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) if (dce && fullrep) { 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); + netdev_warn(dev, "Too many PVCs while sending LMI full report\n"); return; } } skb = dev_alloc_skb(len); if (!skb) { - printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", - dev->name); + netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n"); return; } memset(skb->data, 0, len); skb_reserve(skb, 4); if (lmi == LMI_CISCO) { - skb->protocol = __constant_htons(NLPID_CISCO_LMI); + skb->protocol = cpu_to_be16(NLPID_CISCO_LMI); fr_hard_header(&skb, LMI_CISCO_DLCI); } else { - skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); + skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI); fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); } data = skb_tail_pointer(skb); @@ -643,8 +612,7 @@ static void fr_timer(unsigned long arg) 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); + netdev_info(dev, "No LMI status reply received\n"); state(hdlc)->last_errors |= 1; } @@ -656,8 +624,7 @@ static void fr_timer(unsigned long arg) } if (state(hdlc)->reliable != reliable) { - printk(KERN_INFO "%s: Link %sreliable\n", dev->name, - reliable ? "" : "un"); + netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un"); fr_set_link_state(reliable, dev); } @@ -693,33 +660,32 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH)) { - printk(KERN_INFO "%s: Short LMI frame\n", dev->name); + netdev_info(dev, "Short LMI frame\n"); return 1; } 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); + netdev_info(dev, "Received non-LMI frame with LMI DLCI\n"); return 1; } if (skb->data[4] != LMI_CALLREF) { - printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", - dev->name, skb->data[4]); + netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n", + skb->data[4]); return 1; } if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { - printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", - dev->name, skb->data[5]); + netdev_info(dev, "Invalid LMI Message type (0x%02X)\n", + skb->data[5]); return 1; } if (lmi == LMI_ANSI) { if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { - printk(KERN_INFO "%s: Not ANSI locking shift in LMI" - " message (0x%02X)\n", dev->name, skb->data[6]); + netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n", + skb->data[6]); return 1; } i = 7; @@ -728,34 +694,34 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : LMI_ANSI_CISCO_REPTYPE)) { - printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", - dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != LMI_REPT_LEN) { - printk(KERN_INFO "%s: Invalid LMI Report type IE length" - " (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI Report type IE length (%u)\n", + skb->data[i]); return 1; } reptype = skb->data[++i]; if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { - printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", - dev->name, reptype); + netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n", + reptype); return 1; } if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE)) { - printk(KERN_INFO "%s: Not an LMI Link integrity verification" - " IE (0x%02X)\n", dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != LMI_INTEG_LEN) { - printk(KERN_INFO "%s: Invalid LMI Link integrity verification" - " IE length (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n", + skb->data[i]); return 1; } i++; @@ -829,14 +795,14 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : LMI_ANSI_CISCO_PVCSTAT)) { - printk(KERN_INFO "%s: Not an LMI PVC status IE" - " (0x%02X)\n", dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != stat_len) { - printk(KERN_INFO "%s: Invalid LMI PVC status IE length" - " (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n", + skb->data[i]); return 1; } i++; @@ -857,9 +823,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) pvc = add_pvc(dev, dlci); if (!pvc && !no_ram) { - printk(KERN_WARNING - "%s: Memory squeeze on fr_lmi_recv()\n", - dev->name); + netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n"); no_ram = 1; } @@ -930,8 +894,8 @@ static int fr_rx(struct sk_buff *skb) pvc = find_pvc(hdlc, dlci); if (!pvc) { #ifdef DEBUG_PKT - printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", - frad->name, dlci); + netdev_info(frad, "No PVC for received frame's DLCI %d\n", + dlci); #endif dev_kfree_skb_any(skb); return NET_RX_DROP; @@ -955,7 +919,7 @@ static int fr_rx(struct sk_buff *skb) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - dev_to_hdlc(frad)->stats.rx_dropped++; + frad->stats.rx_dropped++; return NET_RX_DROP; } @@ -990,24 +954,24 @@ static int fr_rx(struct sk_buff *skb) break; default: - printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " - "PID=%x\n", frad->name, oui, pid); + netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n", + oui, pid); dev_kfree_skb_any(skb); return NET_RX_DROP; } } else { - printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " - "length = %i\n", frad->name, data[3], skb->len); + netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n", + data[3], skb->len); dev_kfree_skb_any(skb); return NET_RX_DROP; } if (dev) { - struct net_device_stats *stats = pvc_get_stats(dev); - stats->rx_packets++; /* PVC traffic */ - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; /* PVC traffic */ + dev->stats.rx_bytes += skb->len; if (pvc->state.becn) - stats->rx_compressed++; + dev->stats.rx_compressed++; + skb->dev = dev; netif_rx(skb); return NET_RX_SUCCESS; } else { @@ -1016,7 +980,7 @@ static int fr_rx(struct sk_buff *skb) } rx_error: - dev_to_hdlc(frad)->stats.rx_errors++; /* Mark error */ + frad->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -1082,22 +1046,26 @@ static void pvc_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT; dev->hard_header_len = 10; dev->addr_len = 2; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } +static const struct net_device_ops pvc_ops = { + .ndo_open = pvc_open, + .ndo_stop = pvc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = pvc_xmit, + .ndo_do_ioctl = pvc_ioctl, +}; + static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) { hdlc_device *hdlc = dev_to_hdlc(frad); - pvc_device *pvc = NULL; + pvc_device *pvc; struct net_device *dev; - int result, used; - char * prefix = "pvc%d"; - - if (type == ARPHRD_ETHER) - prefix = "pvceth%d"; + int used; if ((pvc = add_pvc(frad, dlci)) == NULL) { - printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", - frad->name); + netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n"); return -ENOBUFS; } @@ -1106,41 +1074,28 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) used = pvc_is_used(pvc); - if (type == ARPHRD_ETHER) - dev = alloc_netdev(sizeof(struct pvc_desc), "pvceth%d", - ether_setup); - else - dev = alloc_netdev(sizeof(struct pvc_desc), "pvc%d", pvc_setup); + if (type == ARPHRD_ETHER) { + dev = alloc_netdev(0, "pvceth%d", ether_setup); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } else + dev = alloc_netdev(0, "pvc%d", pvc_setup); if (!dev) { - printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", - frad->name); + netdev_warn(frad, "Memory squeeze on fr_pvc()\n"); delete_unused_pvcs(hdlc); return -ENOBUFS; } if (type == ARPHRD_ETHER) - random_ether_addr(dev->dev_addr); + eth_hw_addr_random(dev); else { *(__be16*)dev->dev_addr = htons(dlci); dlci_to_q922(dev->broadcast, dlci); } - dev->hard_start_xmit = pvc_xmit; - dev->get_stats = pvc_get_stats; - dev->open = pvc_open; - dev->stop = pvc_close; - dev->do_ioctl = pvc_ioctl; - dev->change_mtu = pvc_change_mtu; + dev->netdev_ops = &pvc_ops; dev->mtu = HDLC_MAX_MTU; dev->tx_queue_len = 0; - pvcdev_to_desc(dev)->pvc = pvc; - - result = dev_alloc_name(dev, dev->name); - if (result < 0) { - free_netdev(dev); - delete_unused_pvcs(hdlc); - return result; - } + dev->ml_priv = pvc; if (register_netdevice(dev) != 0) { free_netdev(dev); @@ -1243,10 +1198,10 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; case IF_PROTO_FR: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, fr_s, size)) @@ -1282,8 +1237,6 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) state(hdlc)->dce_pvc_count = 0; } memcpy(&state(hdlc)->settings, &new_settings, size); - - dev->hard_start_xmit = hdlc->xmit; dev->type = ARPHRD_FRAD; return 0; @@ -1294,7 +1247,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ return -EINVAL; - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 10396d9686f..0d7645581f9 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -2,104 +2,654 @@ * Generic HDLC support routines for Linux * Point-to-point protocol support * - * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> -#include <linux/rtnetlink.h> -#include <linux/hdlc.h> -#include <net/syncppp.h> +#include <linux/poll.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#define DEBUG_CP 0 /* also bytes# to dump */ +#define DEBUG_STATE 0 +#define DEBUG_HARD_HEADER 0 + +#define HDLC_ADDR_ALLSTATIONS 0xFF +#define HDLC_CTRL_UI 0x03 + +#define PID_LCP 0xC021 +#define PID_IP 0x0021 +#define PID_IPCP 0x8021 +#define PID_IPV6 0x0057 +#define PID_IPV6CP 0x8057 + +enum {IDX_LCP = 0, IDX_IPCP, IDX_IPV6CP, IDX_COUNT}; +enum {CP_CONF_REQ = 1, CP_CONF_ACK, CP_CONF_NAK, CP_CONF_REJ, CP_TERM_REQ, + CP_TERM_ACK, CP_CODE_REJ, LCP_PROTO_REJ, LCP_ECHO_REQ, LCP_ECHO_REPLY, + LCP_DISC_REQ, CP_CODES}; +#if DEBUG_CP +static const char *const code_names[CP_CODES] = { + "0", "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq", + "TermAck", "CodeRej", "ProtoRej", "EchoReq", "EchoReply", "Discard" +}; +static char debug_buffer[64 + 3 * DEBUG_CP]; +#endif + +enum {LCP_OPTION_MRU = 1, LCP_OPTION_ACCM, LCP_OPTION_MAGIC = 5}; + +struct hdlc_header { + u8 address; + u8 control; + __be16 protocol; +}; + +struct cp_header { + u8 code; + u8 id; + __be16 len; +}; + + +struct proto { + struct net_device *dev; + struct timer_list timer; + unsigned long timeout; + u16 pid; /* protocol ID */ + u8 state; + u8 cr_id; /* ID of last Configuration-Request */ + u8 restart_counter; +}; -struct ppp_state { - struct ppp_device pppdev; - struct ppp_device *syncppp_ptr; - int (*old_change_mtu)(struct net_device *dev, int new_mtu); +struct ppp { + struct proto protos[IDX_COUNT]; + spinlock_t lock; + unsigned long last_pong; + unsigned int req_timeout, cr_retries, term_retries; + unsigned int keepalive_interval, keepalive_timeout; + u8 seq; /* local sequence number for requests */ + u8 echo_id; /* ID of last Echo-Request (LCP) */ }; +enum {CLOSED = 0, STOPPED, STOPPING, REQ_SENT, ACK_RECV, ACK_SENT, OPENED, + STATES, STATE_MASK = 0xF}; +enum {START = 0, STOP, TO_GOOD, TO_BAD, RCR_GOOD, RCR_BAD, RCA, RCN, RTR, RTA, + RUC, RXJ_GOOD, RXJ_BAD, EVENTS}; +enum {INV = 0x10, IRC = 0x20, ZRC = 0x40, SCR = 0x80, SCA = 0x100, + SCN = 0x200, STR = 0x400, STA = 0x800, SCJ = 0x1000}; + +#if DEBUG_STATE +static const char *const state_names[STATES] = { + "Closed", "Stopped", "Stopping", "ReqSent", "AckRecv", "AckSent", + "Opened" +}; +static const char *const event_names[EVENTS] = { + "Start", "Stop", "TO+", "TO-", "RCR+", "RCR-", "RCA", "RCN", + "RTR", "RTA", "RUC", "RXJ+", "RXJ-" +}; +#endif + +static struct sk_buff_head tx_queue; /* used when holding the spin lock */ + static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr); +static inline struct ppp* get_ppp(struct net_device *dev) +{ + return (struct ppp *)dev_to_hdlc(dev)->state; +} -static inline struct ppp_state* state(hdlc_device *hdlc) +static inline struct proto* get_proto(struct net_device *dev, u16 pid) { - return(struct ppp_state *)(hdlc->state); + struct ppp *ppp = get_ppp(dev); + + switch (pid) { + case PID_LCP: + return &ppp->protos[IDX_LCP]; + case PID_IPCP: + return &ppp->protos[IDX_IPCP]; + case PID_IPV6CP: + return &ppp->protos[IDX_IPV6CP]; + default: + return NULL; + } } +static inline const char* proto_name(u16 pid) +{ + switch (pid) { + case PID_LCP: + return "LCP"; + case PID_IPCP: + return "IPCP"; + case PID_IPV6CP: + return "IPV6CP"; + default: + return NULL; + } +} -static int ppp_open(struct net_device *dev) +static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - int (*old_ioctl)(struct net_device *, struct ifreq *, int); - int result; + struct hdlc_header *data = (struct hdlc_header*)skb->data; + + if (skb->len < sizeof(struct hdlc_header)) + return htons(ETH_P_HDLC); + if (data->address != HDLC_ADDR_ALLSTATIONS || + data->control != HDLC_CTRL_UI) + return htons(ETH_P_HDLC); + + switch (data->protocol) { + case cpu_to_be16(PID_IP): + skb_pull(skb, sizeof(struct hdlc_header)); + return htons(ETH_P_IP); - dev->priv = &state(hdlc)->syncppp_ptr; - state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev; - state(hdlc)->pppdev.dev = dev; + case cpu_to_be16(PID_IPV6): + skb_pull(skb, sizeof(struct hdlc_header)); + return htons(ETH_P_IPV6); - old_ioctl = dev->do_ioctl; - 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; - state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO; - dev->type = ARPHRD_PPP; - result = sppp_open(dev); - if (result) { - sppp_detach(dev); - return result; + default: + return htons(ETH_P_HDLC); } +} - return 0; + +static int ppp_hard_header(struct sk_buff *skb, struct net_device *dev, + u16 type, const void *daddr, const void *saddr, + unsigned int len) +{ + struct hdlc_header *data; +#if DEBUG_HARD_HEADER + printk(KERN_DEBUG "%s: ppp_hard_header() called\n", dev->name); +#endif + + skb_push(skb, sizeof(struct hdlc_header)); + data = (struct hdlc_header*)skb->data; + + data->address = HDLC_ADDR_ALLSTATIONS; + data->control = HDLC_CTRL_UI; + switch (type) { + case ETH_P_IP: + data->protocol = htons(PID_IP); + break; + case ETH_P_IPV6: + data->protocol = htons(PID_IPV6); + break; + case PID_LCP: + case PID_IPCP: + case PID_IPV6CP: + data->protocol = htons(type); + break; + default: /* unknown protocol */ + data->protocol = 0; + } + return sizeof(struct hdlc_header); } +static void ppp_tx_flush(void) +{ + struct sk_buff *skb; + while ((skb = skb_dequeue(&tx_queue)) != NULL) + dev_queue_xmit(skb); +} -static void ppp_close(struct net_device *dev) +static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code, + u8 id, unsigned int len, const void *data) { - hdlc_device *hdlc = dev_to_hdlc(dev); + struct sk_buff *skb; + struct cp_header *cp; + unsigned int magic_len = 0; + static u32 magic; + +#if DEBUG_CP + int i; + char *ptr; +#endif + + if (pid == PID_LCP && (code == LCP_ECHO_REQ || code == LCP_ECHO_REPLY)) + magic_len = sizeof(magic); + + skb = dev_alloc_skb(sizeof(struct hdlc_header) + + sizeof(struct cp_header) + magic_len + len); + if (!skb) { + netdev_warn(dev, "out of memory in ppp_tx_cp()\n"); + return; + } + skb_reserve(skb, sizeof(struct hdlc_header)); + + cp = (struct cp_header *)skb_put(skb, sizeof(struct cp_header)); + cp->code = code; + cp->id = id; + cp->len = htons(sizeof(struct cp_header) + magic_len + len); + + if (magic_len) + memcpy(skb_put(skb, magic_len), &magic, magic_len); + if (len) + memcpy(skb_put(skb, len), data, len); + +#if DEBUG_CP + BUG_ON(code >= CP_CODES); + ptr = debug_buffer; + *ptr = '\x0'; + for (i = 0; i < min_t(unsigned int, magic_len + len, DEBUG_CP); i++) { + sprintf(ptr, " %02X", skb->data[sizeof(struct cp_header) + i]); + ptr += strlen(ptr); + } + printk(KERN_DEBUG "%s: TX %s [%s id 0x%X]%s\n", dev->name, + proto_name(pid), code_names[code], id, debug_buffer); +#endif - sppp_close(dev); - sppp_detach(dev); + ppp_hard_header(skb, dev, pid, NULL, NULL, 0); - dev->change_mtu = state(hdlc)->old_change_mtu; - dev->mtu = HDLC_MAX_MTU; - dev->hard_header_len = 16; + skb->priority = TC_PRIO_CONTROL; + skb->dev = dev; + skb_reset_network_header(skb); + skb_queue_tail(&tx_queue, skb); } +/* State transition table (compare STD-51) + Events Actions + TO+ = Timeout with counter > 0 irc = Initialize-Restart-Count + TO- = Timeout with counter expired zrc = Zero-Restart-Count + + RCR+ = Receive-Configure-Request (Good) scr = Send-Configure-Request + RCR- = Receive-Configure-Request (Bad) + RCA = Receive-Configure-Ack sca = Send-Configure-Ack + RCN = Receive-Configure-Nak/Rej scn = Send-Configure-Nak/Rej + + RTR = Receive-Terminate-Request str = Send-Terminate-Request + RTA = Receive-Terminate-Ack sta = Send-Terminate-Ack + + RUC = Receive-Unknown-Code scj = Send-Code-Reject + RXJ+ = Receive-Code-Reject (permitted) + or Receive-Protocol-Reject + RXJ- = Receive-Code-Reject (catastrophic) + or Receive-Protocol-Reject +*/ +static int cp_table[EVENTS][STATES] = { + /* CLOSED STOPPED STOPPING REQ_SENT ACK_RECV ACK_SENT OPENED + 0 1 2 3 4 5 6 */ + {IRC|SCR|3, INV , INV , INV , INV , INV , INV }, /* START */ + { INV , 0 , 0 , 0 , 0 , 0 , 0 }, /* STOP */ + { INV , INV ,STR|2, SCR|3 ,SCR|3, SCR|5 , INV }, /* TO+ */ + { INV , INV , 1 , 1 , 1 , 1 , INV }, /* TO- */ + { STA|0 ,IRC|SCR|SCA|5, 2 , SCA|5 ,SCA|6, SCA|5 ,SCR|SCA|5}, /* RCR+ */ + { STA|0 ,IRC|SCR|SCN|3, 2 , SCN|3 ,SCN|4, SCN|3 ,SCR|SCN|3}, /* RCR- */ + { STA|0 , STA|1 , 2 , IRC|4 ,SCR|3, 6 , SCR|3 }, /* RCA */ + { STA|0 , STA|1 , 2 ,IRC|SCR|3,SCR|3,IRC|SCR|5, SCR|3 }, /* RCN */ + { STA|0 , STA|1 ,STA|2, STA|3 ,STA|3, STA|3 ,ZRC|STA|2}, /* RTR */ + { 0 , 1 , 1 , 3 , 3 , 5 , SCR|3 }, /* RTA */ + { SCJ|0 , SCJ|1 ,SCJ|2, SCJ|3 ,SCJ|4, SCJ|5 , SCJ|6 }, /* RUC */ + { 0 , 1 , 2 , 3 , 3 , 5 , 6 }, /* RXJ+ */ + { 0 , 1 , 1 , 1 , 1 , 1 ,IRC|STR|2}, /* RXJ- */ +}; -static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) + +/* SCA: RCR+ must supply id, len and data + SCN: RCR- must supply code, id, len and data + STA: RTR must supply id + SCJ: RUC must supply CP packet len and data */ +static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code, + u8 id, unsigned int len, const void *data) { - return __constant_htons(ETH_P_WAN_PPP); + int old_state, action; + struct ppp *ppp = get_ppp(dev); + struct proto *proto = get_proto(dev, pid); + + old_state = proto->state; + BUG_ON(old_state >= STATES); + BUG_ON(event >= EVENTS); + +#if DEBUG_STATE + printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) %s ...\n", dev->name, + proto_name(pid), event_names[event], state_names[proto->state]); +#endif + + action = cp_table[event][old_state]; + + proto->state = action & STATE_MASK; + if (action & (SCR | STR)) /* set Configure-Req/Terminate-Req timer */ + mod_timer(&proto->timer, proto->timeout = + jiffies + ppp->req_timeout * HZ); + if (action & ZRC) + proto->restart_counter = 0; + if (action & IRC) + proto->restart_counter = (proto->state == STOPPING) ? + ppp->term_retries : ppp->cr_retries; + + if (action & SCR) /* send Configure-Request */ + ppp_tx_cp(dev, pid, CP_CONF_REQ, proto->cr_id = ++ppp->seq, + 0, NULL); + if (action & SCA) /* send Configure-Ack */ + ppp_tx_cp(dev, pid, CP_CONF_ACK, id, len, data); + if (action & SCN) /* send Configure-Nak/Reject */ + ppp_tx_cp(dev, pid, code, id, len, data); + if (action & STR) /* send Terminate-Request */ + ppp_tx_cp(dev, pid, CP_TERM_REQ, ++ppp->seq, 0, NULL); + if (action & STA) /* send Terminate-Ack */ + ppp_tx_cp(dev, pid, CP_TERM_ACK, id, 0, NULL); + if (action & SCJ) /* send Code-Reject */ + ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data); + + if (old_state != OPENED && proto->state == OPENED) { + netdev_info(dev, "%s up\n", proto_name(pid)); + if (pid == PID_LCP) { + netif_dormant_off(dev); + ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL); + ppp_cp_event(dev, PID_IPV6CP, START, 0, 0, 0, NULL); + ppp->last_pong = jiffies; + mod_timer(&proto->timer, proto->timeout = + jiffies + ppp->keepalive_interval * HZ); + } + } + if (old_state == OPENED && proto->state != OPENED) { + netdev_info(dev, "%s down\n", proto_name(pid)); + if (pid == PID_LCP) { + netif_dormant_on(dev); + ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL); + ppp_cp_event(dev, PID_IPV6CP, STOP, 0, 0, 0, NULL); + } + } + if (old_state != CLOSED && proto->state == CLOSED) + del_timer(&proto->timer); + +#if DEBUG_STATE + printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) ... %s\n", dev->name, + proto_name(pid), event_names[event], state_names[proto->state]); +#endif } +static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id, + unsigned int req_len, const u8 *data) +{ + static u8 const valid_accm[6] = { LCP_OPTION_ACCM, 6, 0, 0, 0, 0 }; + const u8 *opt; + u8 *out; + unsigned int len = req_len, nak_len = 0, rej_len = 0; + + if (!(out = kmalloc(len, GFP_ATOMIC))) { + dev->stats.rx_dropped++; + return; /* out of memory, ignore CR packet */ + } + + for (opt = data; len; len -= opt[1], opt += opt[1]) { + if (len < 2 || len < opt[1]) { + dev->stats.rx_errors++; + kfree(out); + return; /* bad packet, drop silently */ + } + + if (pid == PID_LCP) + switch (opt[0]) { + case LCP_OPTION_MRU: + continue; /* MRU always OK and > 1500 bytes? */ + + case LCP_OPTION_ACCM: /* async control character map */ + if (!memcmp(opt, valid_accm, + sizeof(valid_accm))) + continue; + if (!rej_len) { /* NAK it */ + memcpy(out + nak_len, valid_accm, + sizeof(valid_accm)); + nak_len += sizeof(valid_accm); + continue; + } + break; + case LCP_OPTION_MAGIC: + if (opt[1] != 6 || (!opt[2] && !opt[3] && + !opt[4] && !opt[5])) + break; /* reject invalid magic number */ + continue; + } + /* reject this option */ + memcpy(out + rej_len, opt, opt[1]); + rej_len += opt[1]; + } + + if (rej_len) + ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_REJ, id, rej_len, out); + else if (nak_len) + ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_NAK, id, nak_len, out); + else + ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data); + + kfree(out); +} + +static int ppp_rx(struct sk_buff *skb) +{ + struct hdlc_header *hdr = (struct hdlc_header*)skb->data; + struct net_device *dev = skb->dev; + struct ppp *ppp = get_ppp(dev); + struct proto *proto; + struct cp_header *cp; + unsigned long flags; + unsigned int len; + u16 pid; +#if DEBUG_CP + int i; + char *ptr; +#endif + + spin_lock_irqsave(&ppp->lock, flags); + /* Check HDLC header */ + if (skb->len < sizeof(struct hdlc_header)) + goto rx_error; + cp = (struct cp_header*)skb_pull(skb, sizeof(struct hdlc_header)); + if (hdr->address != HDLC_ADDR_ALLSTATIONS || + hdr->control != HDLC_CTRL_UI) + goto rx_error; + + pid = ntohs(hdr->protocol); + proto = get_proto(dev, pid); + if (!proto) { + if (ppp->protos[IDX_LCP].state == OPENED) + ppp_tx_cp(dev, PID_LCP, LCP_PROTO_REJ, + ++ppp->seq, skb->len + 2, &hdr->protocol); + goto rx_error; + } + + len = ntohs(cp->len); + if (len < sizeof(struct cp_header) /* no complete CP header? */ || + skb->len < len /* truncated packet? */) + goto rx_error; + skb_pull(skb, sizeof(struct cp_header)); + len -= sizeof(struct cp_header); + + /* HDLC and CP headers stripped from skb */ +#if DEBUG_CP + if (cp->code < CP_CODES) + sprintf(debug_buffer, "[%s id 0x%X]", code_names[cp->code], + cp->id); + else + sprintf(debug_buffer, "[code %u id 0x%X]", cp->code, cp->id); + ptr = debug_buffer + strlen(debug_buffer); + for (i = 0; i < min_t(unsigned int, len, DEBUG_CP); i++) { + sprintf(ptr, " %02X", skb->data[i]); + ptr += strlen(ptr); + } + printk(KERN_DEBUG "%s: RX %s %s\n", dev->name, proto_name(pid), + debug_buffer); +#endif + + /* LCP only */ + if (pid == PID_LCP) + switch (cp->code) { + case LCP_PROTO_REJ: + pid = ntohs(*(__be16*)skb->data); + if (pid == PID_LCP || pid == PID_IPCP || + pid == PID_IPV6CP) + ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, + 0, NULL); + goto out; + + case LCP_ECHO_REQ: /* send Echo-Reply */ + if (len >= 4 && proto->state == OPENED) + ppp_tx_cp(dev, PID_LCP, LCP_ECHO_REPLY, + cp->id, len - 4, skb->data + 4); + goto out; + + case LCP_ECHO_REPLY: + if (cp->id == ppp->echo_id) + ppp->last_pong = jiffies; + goto out; + + case LCP_DISC_REQ: /* discard */ + goto out; + } + + /* LCP, IPCP and IPV6CP */ + switch (cp->code) { + case CP_CONF_REQ: + ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data); + break; + + case CP_CONF_ACK: + if (cp->id == proto->cr_id) + ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL); + break; + + case CP_CONF_REJ: + case CP_CONF_NAK: + if (cp->id == proto->cr_id) + ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL); + break; + + case CP_TERM_REQ: + ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL); + break; + + case CP_TERM_ACK: + ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL); + break; + + case CP_CODE_REJ: + ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL); + break; + + default: + len += sizeof(struct cp_header); + if (len > dev->mtu) + len = dev->mtu; + ppp_cp_event(dev, pid, RUC, 0, 0, len, cp); + break; + } + goto out; + +rx_error: + dev->stats.rx_errors++; +out: + spin_unlock_irqrestore(&ppp->lock, flags); + dev_kfree_skb_any(skb); + ppp_tx_flush(); + return NET_RX_DROP; +} + +static void ppp_timer(unsigned long arg) +{ + struct proto *proto = (struct proto *)arg; + struct ppp *ppp = get_ppp(proto->dev); + unsigned long flags; + + spin_lock_irqsave(&ppp->lock, flags); + switch (proto->state) { + case STOPPING: + case REQ_SENT: + case ACK_RECV: + case ACK_SENT: + if (proto->restart_counter) { + ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0, + 0, NULL); + proto->restart_counter--; + } else + ppp_cp_event(proto->dev, proto->pid, TO_BAD, 0, 0, + 0, NULL); + break; + + case OPENED: + if (proto->pid != PID_LCP) + break; + if (time_after(jiffies, ppp->last_pong + + ppp->keepalive_timeout * HZ)) { + netdev_info(proto->dev, "Link down\n"); + ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL); + ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL); + } else { /* send keep-alive packet */ + ppp->echo_id = ++ppp->seq; + ppp_tx_cp(proto->dev, PID_LCP, LCP_ECHO_REQ, + ppp->echo_id, 0, NULL); + proto->timer.expires = jiffies + + ppp->keepalive_interval * HZ; + add_timer(&proto->timer); + } + break; + } + spin_unlock_irqrestore(&ppp->lock, flags); + ppp_tx_flush(); +} + + +static void ppp_start(struct net_device *dev) +{ + struct ppp *ppp = get_ppp(dev); + int i; + + for (i = 0; i < IDX_COUNT; i++) { + struct proto *proto = &ppp->protos[i]; + proto->dev = dev; + init_timer(&proto->timer); + proto->timer.function = ppp_timer; + proto->timer.data = (unsigned long)proto; + proto->state = CLOSED; + } + ppp->protos[IDX_LCP].pid = PID_LCP; + ppp->protos[IDX_IPCP].pid = PID_IPCP; + ppp->protos[IDX_IPV6CP].pid = PID_IPV6CP; + + ppp_cp_event(dev, PID_LCP, START, 0, 0, 0, NULL); +} + +static void ppp_stop(struct net_device *dev) +{ + ppp_cp_event(dev, PID_LCP, STOP, 0, 0, 0, NULL); +} + +static void ppp_close(struct net_device *dev) +{ + ppp_tx_flush(); +} static struct hdlc_proto proto = { - .open = ppp_open, + .start = ppp_start, + .stop = ppp_stop, .close = ppp_close, .type_trans = ppp_type_trans, .ioctl = ppp_ioctl, + .netif_rx = ppp_rx, .module = THIS_MODULE, }; +static const struct header_ops ppp_header_ops = { + .create = ppp_hard_header, +}; static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) { hdlc_device *hdlc = dev_to_hdlc(dev); + struct ppp *ppp; int result; switch (ifr->ifr_settings.type) { @@ -110,25 +660,34 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; /* return protocol only, no settable parameters */ case IF_PROTO_PPP: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; /* no settable parameters */ - result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result = hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; - result = attach_hdlc_protocol(dev, &proto, - sizeof(struct ppp_state)); + result = attach_hdlc_protocol(dev, &proto, sizeof(struct ppp)); if (result) return result; - dev->hard_start_xmit = hdlc->xmit; + + ppp = get_ppp(dev); + spin_lock_init(&ppp->lock); + ppp->req_timeout = 2; + ppp->cr_retries = 10; + ppp->term_retries = 2; + ppp->keepalive_interval = 10; + ppp->keepalive_timeout = 60; + + dev->hard_header_len = sizeof(struct hdlc_header); + dev->header_ops = &ppp_header_ops; dev->type = ARPHRD_PPP; - netif_dormant_off(dev); + netif_dormant_on(dev); return 0; } @@ -138,12 +697,11 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) static int __init mod_init(void) { + skb_queue_head_init(&tx_queue); register_hdlc_protocol(&proto); return 0; } - - static void __exit mod_exit(void) { unregister_hdlc_protocol(&proto); diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index bbbb819d764..5dc153e8a29 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -9,30 +9,26 @@ * as published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/hdlc.h> +#include <linux/skbuff.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); + return cpu_to_be16(ETH_P_IP); } - - static struct hdlc_proto proto = { .type_trans = raw_type_trans, .ioctl = raw_ioctl, @@ -87,7 +83,6 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; memcpy(hdlc->state, &new_settings, size); - dev->hard_start_xmit = hdlc->xmit; dev->type = ARPHRD_RAWHDLC; netif_dormant_off(dev); return 0; diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index d20c685f671..3ab72b3082d 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c @@ -9,31 +9,30 @@ * as published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/etherdevice.h> +#include <linux/gfp.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/etherdevice.h> -#include <linux/hdlc.h> +#include <linux/skbuff.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) +static netdev_tx_t eth_tx(struct sk_buff *skb, struct net_device *dev) { int pad = ETH_ZLEN - skb->len; if (pad > 0) { /* Pad the frame with zeros */ int len = skb->len; if (skb_tailroom(skb) < pad) if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { - hdlc_stats(dev)->tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); return 0; } @@ -46,6 +45,7 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev) static struct hdlc_proto proto = { .type_trans = eth_type_trans, + .xmit = eth_tx, .ioctl = raw_eth_ioctl, .module = THIS_MODULE, }; @@ -57,9 +57,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - int (*old_ch_mtu)(struct net_device *, int); - int old_qlen; + int result, old_qlen; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: @@ -100,13 +98,10 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) 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; ether_setup(dev); - dev->change_mtu = old_ch_mtu; dev->tx_queue_len = old_qlen; - random_ether_addr(dev->dev_addr); + eth_hw_addr_random(dev); netif_dormant_off(dev); return 0; } diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index c15cc11e399..a49aec5efd2 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -9,20 +9,19 @@ * as published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/gfp.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> -#include <linux/init.h> -#include <linux/skbuff.h> -#include <linux/pkt_sched.h> #include <linux/inetdevice.h> +#include <linux/init.h> +#include <linux/kernel.h> #include <linux/lapb.h> +#include <linux/module.h> +#include <linux/pkt_sched.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/hdlc.h> - +#include <linux/skbuff.h> #include <net/x25device.h> static int x25_ioctl(struct net_device *dev, struct ifreq *ifr); @@ -35,7 +34,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) unsigned char *ptr; if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "%s: out of memory\n", dev->name); + netdev_err(dev, "out of memory\n"); return; } @@ -50,14 +49,14 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) static void x25_connected(struct net_device *dev, int reason) { - x25_connect_disconnect(dev, reason, 1); + x25_connect_disconnect(dev, reason, X25_IFACE_CONNECT); } static void x25_disconnected(struct net_device *dev, int reason) { - x25_connect_disconnect(dev, reason, 2); + x25_connect_disconnect(dev, reason, X25_IFACE_DISCONNECT); } @@ -72,7 +71,7 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) return NET_RX_DROP; ptr = skb->data; - *ptr = 0; + *ptr = X25_IFACE_DATA; skb->protocol = x25_type_trans(skb, dev); return netif_rx(skb); @@ -88,40 +87,38 @@ static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb) -static int x25_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev) { int result; /* X.25 to LAPB */ switch (skb->data[0]) { - case 0: /* Data to be transmitted */ + case X25_IFACE_DATA: /* Data to be transmitted */ skb_pull(skb, 1); if ((result = lapb_data_request(dev, skb)) != LAPB_OK) dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; - case 1: + case X25_IFACE_CONNECT: if ((result = lapb_connect_request(dev))!= LAPB_OK) { if (result == LAPB_CONNECTED) /* Send connect confirm. msg to level 3 */ x25_connected(dev, 0); else - printk(KERN_ERR "%s: LAPB connect request " - "failed, error code = %i\n", - dev->name, result); + netdev_err(dev, "LAPB connect request failed, error code = %i\n", + result); } break; - case 2: + case X25_IFACE_DISCONNECT: if ((result = lapb_disconnect_request(dev)) != LAPB_OK) { if (result == LAPB_NOTCONNECTED) /* Send disconnect confirm. msg to level 3 */ x25_disconnected(dev, 0); else - printk(KERN_ERR "%s: LAPB disconnect request " - "failed, error code = %i\n", - dev->name, result); + netdev_err(dev, "LAPB disconnect request failed, error code = %i\n", + result); } break; @@ -130,22 +127,22 @@ static int x25_xmit(struct sk_buff *skb, struct net_device *dev) } dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } static int x25_open(struct net_device *dev) { - struct lapb_register_struct cb; int result; - - cb.connect_confirmation = x25_connected; - cb.connect_indication = x25_connected; - cb.disconnect_confirmation = x25_disconnected; - cb.disconnect_indication = x25_disconnected; - cb.data_indication = x25_data_indication; - cb.data_transmit = x25_data_transmit; + static const struct lapb_register_struct cb = { + .connect_confirmation = x25_connected, + .connect_indication = x25_connected, + .disconnect_confirmation = x25_disconnected, + .disconnect_indication = x25_disconnected, + .data_indication = x25_data_indication, + .data_transmit = x25_data_transmit, + }; result = lapb_register(dev, &cb); if (result != LAPB_OK) @@ -164,17 +161,17 @@ static void x25_close(struct net_device *dev) static int x25_rx(struct sk_buff *skb) { - struct hdlc_device *hdlc = dev_to_hdlc(skb->dev); + struct net_device *dev = skb->dev; if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - hdlc->stats.rx_dropped++; + dev->stats.rx_dropped++; return NET_RX_DROP; } - if (lapb_data_received(skb->dev, skb) == LAPB_OK) + if (lapb_data_received(dev, skb) == LAPB_OK) return NET_RX_SUCCESS; - hdlc->stats.rx_errors++; + dev->stats.rx_errors++; dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -185,6 +182,7 @@ static struct hdlc_proto proto = { .close = x25_close, .ioctl = x25_ioctl, .netif_rx = x25_rx, + .xmit = x25_xmit, .module = THIS_MODULE, }; @@ -202,10 +200,10 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; /* return protocol only, no settable parameters */ case IF_PROTO_X25: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); @@ -214,7 +212,6 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) if ((result = attach_hdlc_protocol(dev, &proto, 0))) return result; - dev->hard_start_xmit = x25_xmit; dev->type = ARPHRD_X25; netif_dormant_off(dev); return 0; diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 83dbc924fcb..3d741663fd6 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -15,9 +15,13 @@ * The hardware does the bus handling to avoid the need for delays between * touching control registers. * - * Port B isnt wired (why - beats me) + * Port B isn't wired (why - beats me) + * + * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -26,98 +30,91 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/delay.h> +#include <linux/hdlc.h> #include <linux/ioport.h> +#include <linux/slab.h> #include <net/arp.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/dma.h> #include <asm/byteorder.h> -#include <net/syncppp.h> #include "z85230.h" static int dma; -struct sv11_device -{ - void *if_ptr; /* General purpose pointer (used by SPPP) */ - struct z8530_dev sync; - struct ppp_device netdev; -}; - /* * Network driver support routines */ +static inline struct z8530_dev* dev_to_sv(struct net_device *dev) +{ + return (struct z8530_dev *)dev_to_hdlc(dev)->priv; +} + /* - * Frame receive. Simple for our card as we do sync ppp and there + * Frame receive. Simple for our card as we do HDLC and there * is no funny garbage involved */ - + static void hostess_input(struct z8530_channel *c, struct sk_buff *skb) { /* Drop the CRC - it's not a good idea to try and negotiate it ;) */ - skb_trim(skb, skb->len-2); - skb->protocol=__constant_htons(ETH_P_WAN_PPP); + skb_trim(skb, skb->len - 2); + skb->protocol = hdlc_type_trans(skb, c->netdevice); skb_reset_mac_header(skb); - skb->dev=c->netdevice; + skb->dev = c->netdevice; /* * Send it to the PPP layer. We don't have time to process * it right now. */ netif_rx(skb); - c->netdevice->last_rx = jiffies; } - + /* * We've been placed in the UP state - */ - + */ + static int hostess_open(struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct z8530_dev *sv11 = dev_to_sv(d); int err = -1; - + /* * Link layer up */ - switch(dma) - { + switch (dma) { case 0: - err=z8530_sync_open(d, &sv11->sync.chanA); + err = z8530_sync_open(d, &sv11->chanA); break; case 1: - err=z8530_sync_dma_open(d, &sv11->sync.chanA); + err = z8530_sync_dma_open(d, &sv11->chanA); break; case 2: - err=z8530_sync_txdma_open(d, &sv11->sync.chanA); + err = z8530_sync_txdma_open(d, &sv11->chanA); break; } - - if(err) + + if (err) return err; - /* - * Begin PPP - */ - err=sppp_open(d); - if(err) - { - switch(dma) - { + + err = hdlc_open(d); + if (err) { + switch (dma) { case 0: - z8530_sync_close(d, &sv11->sync.chanA); + z8530_sync_close(d, &sv11->chanA); break; case 1: - z8530_sync_dma_close(d, &sv11->sync.chanA); + z8530_sync_dma_close(d, &sv11->chanA); break; case 2: - z8530_sync_txdma_close(d, &sv11->sync.chanA); + z8530_sync_txdma_close(d, &sv11->chanA); break; - } + } return err; } - sv11->sync.chanA.rx_function=hostess_input; - + sv11->chanA.rx_function = hostess_input; + /* * Go go go */ @@ -128,30 +125,24 @@ static int hostess_open(struct net_device *d) static int hostess_close(struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct z8530_dev *sv11 = dev_to_sv(d); /* * Discard new frames */ - sv11->sync.chanA.rx_function=z8530_null_rx; - /* - * PPP off - */ - sppp_close(d); - /* - * Link layer down - */ + sv11->chanA.rx_function = z8530_null_rx; + + hdlc_close(d); netif_stop_queue(d); - - switch(dma) - { + + switch (dma) { case 0: - z8530_sync_close(d, &sv11->sync.chanA); + z8530_sync_close(d, &sv11->chanA); break; case 1: - z8530_sync_dma_close(d, &sv11->sync.chanA); + z8530_sync_dma_close(d, &sv11->chanA); break; case 2: - z8530_sync_txdma_close(d, &sv11->sync.chanA); + z8530_sync_txdma_close(d, &sv11->chanA); break; } return 0; @@ -159,232 +150,180 @@ static int hostess_close(struct net_device *d) static int hostess_ioctl(struct net_device *d, struct ifreq *ifr, int cmd) { - /* struct sv11_device *sv11=d->priv; - z8530_ioctl(d,&sv11->sync.chanA,ifr,cmd) */ - return sppp_do_ioctl(d, ifr,cmd); -} - -static struct net_device_stats *hostess_get_stats(struct net_device *d) -{ - struct sv11_device *sv11=d->priv; - if(sv11) - return z8530_get_stats(&sv11->sync.chanA); - else - return NULL; + /* struct z8530_dev *sv11=dev_to_sv(d); + z8530_ioctl(d,&sv11->chanA,ifr,cmd) */ + return hdlc_ioctl(d, ifr, cmd); } /* - * Passed PPP frames, fire them downwind. + * Passed network frames, fire them downwind. */ - -static int hostess_queue_xmit(struct sk_buff *skb, struct net_device *d) -{ - struct sv11_device *sv11=d->priv; - return z8530_queue_xmit(&sv11->sync.chanA, skb); -} -static int hostess_neigh_setup(struct neighbour *n) +static netdev_tx_t hostess_queue_xmit(struct sk_buff *skb, + struct net_device *d) { - if (n->nud_state == NUD_NONE) { - n->ops = &arp_broken_ops; - n->output = n->ops->output; - } - return 0; + return z8530_queue_xmit(&dev_to_sv(d)->chanA, skb); } -static int hostess_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) +static int hostess_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - if (p->tbl->family == AF_INET) { - p->neigh_setup = hostess_neigh_setup; - p->ucast_probes = 0; - p->mcast_probes = 0; - } - return 0; -} - -static void sv11_setup(struct net_device *dev) -{ - dev->open = hostess_open; - dev->stop = hostess_close; - dev->hard_start_xmit = hostess_queue_xmit; - dev->get_stats = hostess_get_stats; - dev->do_ioctl = hostess_ioctl; - dev->neigh_setup = hostess_neigh_setup_dev; + if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT) + return 0; + return -EINVAL; } /* * Description block for a Comtrol Hostess SV11 card */ - -static struct sv11_device *sv11_init(int iobase, int irq) + +static const struct net_device_ops hostess_ops = { + .ndo_open = hostess_open, + .ndo_stop = hostess_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hostess_ioctl, +}; + +static struct z8530_dev *sv11_init(int iobase, int irq) { - struct z8530_dev *dev; - struct sv11_device *sv; - + struct z8530_dev *sv; + struct net_device *netdev; /* * Get the needed I/O space */ - - if(!request_region(iobase, 8, "Comtrol SV11")) - { - printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n", iobase); + + if (!request_region(iobase, 8, "Comtrol SV11")) { + pr_warn("I/O 0x%X already in use\n", iobase); return NULL; } - - sv = kzalloc(sizeof(struct sv11_device), GFP_KERNEL); - if(!sv) - goto fail3; - - sv->if_ptr=&sv->netdev; - - sv->netdev.dev = alloc_netdev(0, "hdlc%d", sv11_setup); - if(!sv->netdev.dev) - goto fail2; - - dev=&sv->sync; - + + sv = kzalloc(sizeof(struct z8530_dev), GFP_KERNEL); + if (!sv) + goto err_kzalloc; + /* * Stuff in the I/O addressing */ - - dev->active = 0; - - dev->chanA.ctrlio=iobase+1; - dev->chanA.dataio=iobase+3; - dev->chanB.ctrlio=-1; - dev->chanB.dataio=-1; - dev->chanA.irqs=&z8530_nop; - dev->chanB.irqs=&z8530_nop; - - outb(0, iobase+4); /* DMA off */ - + + sv->active = 0; + + sv->chanA.ctrlio = iobase + 1; + sv->chanA.dataio = iobase + 3; + sv->chanB.ctrlio = -1; + sv->chanB.dataio = -1; + sv->chanA.irqs = &z8530_nop; + sv->chanB.irqs = &z8530_nop; + + outb(0, iobase + 4); /* DMA off */ + /* We want a fast IRQ for this device. Actually we'd like an even faster IRQ ;) - This is one driver RtLinux is made for */ - - if(request_irq(irq, &z8530_interrupt, IRQF_DISABLED, "Hostess SV11", dev)<0) - { - printk(KERN_WARNING "hostess: IRQ %d already in use.\n", irq); - goto fail1; + + if (request_irq(irq, z8530_interrupt, 0, + "Hostess SV11", sv) < 0) { + pr_warn("IRQ %d already in use\n", irq); + goto err_irq; } - - dev->irq=irq; - dev->chanA.private=sv; - dev->chanA.netdevice=sv->netdev.dev; - dev->chanA.dev=dev; - dev->chanB.dev=dev; - - if(dma) - { + + sv->irq = irq; + sv->chanA.private = sv; + sv->chanA.dev = sv; + sv->chanB.dev = sv; + + if (dma) { /* * You can have DMA off or 1 and 3 thats the lot * on the Comtrol. */ - dev->chanA.txdma=3; - dev->chanA.rxdma=1; - outb(0x03|0x08, iobase+4); /* DMA on */ - if(request_dma(dev->chanA.txdma, "Hostess SV/11 (TX)")!=0) - goto fail; - - if(dma==1) - { - if(request_dma(dev->chanA.rxdma, "Hostess SV/11 (RX)")!=0) - goto dmafail; - } + sv->chanA.txdma = 3; + sv->chanA.rxdma = 1; + outb(0x03 | 0x08, iobase + 4); /* DMA on */ + if (request_dma(sv->chanA.txdma, "Hostess SV/11 (TX)")) + goto err_txdma; + + if (dma == 1) + if (request_dma(sv->chanA.rxdma, "Hostess SV/11 (RX)")) + goto err_rxdma; } /* Kill our private IRQ line the hostess can end up chattering until the configuration is set */ disable_irq(irq); - + /* * Begin normal initialise */ - - if(z8530_init(dev)!=0) - { - printk(KERN_ERR "Z8530 series device not found.\n"); + + if (z8530_init(sv)) { + pr_err("Z8530 series device not found\n"); enable_irq(irq); - goto dmafail2; + goto free_dma; } - z8530_channel_load(&dev->chanB, z8530_dead_port); - if(dev->type==Z85C30) - z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream); + z8530_channel_load(&sv->chanB, z8530_dead_port); + if (sv->type == Z85C30) + z8530_channel_load(&sv->chanA, z8530_hdlc_kilostream); else - z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230); - + z8530_channel_load(&sv->chanA, z8530_hdlc_kilostream_85230); + enable_irq(irq); - /* * Now we can take the IRQ */ - if(dev_alloc_name(dev->chanA.netdevice,"hdlc%d")>=0) - { - struct net_device *d=dev->chanA.netdevice; - /* - * Initialise the PPP components - */ - sppp_attach(&sv->netdev); - - /* - * Local fields - */ - - d->base_addr = iobase; - d->irq = irq; - d->priv = sv; - - if(register_netdev(d)) - { - printk(KERN_ERR "%s: unable to register device.\n", - d->name); - sppp_detach(d); - goto dmafail2; - } + sv->chanA.netdevice = netdev = alloc_hdlcdev(sv); + if (!netdev) + goto free_dma; - z8530_describe(dev, "I/O", iobase); - dev->active=1; - return sv; + dev_to_hdlc(netdev)->attach = hostess_attach; + dev_to_hdlc(netdev)->xmit = hostess_queue_xmit; + netdev->netdev_ops = &hostess_ops; + netdev->base_addr = iobase; + netdev->irq = irq; + + if (register_hdlc_device(netdev)) { + pr_err("unable to register HDLC device\n"); + free_netdev(netdev); + goto free_dma; } -dmafail2: - if(dma==1) - free_dma(dev->chanA.rxdma); -dmafail: - if(dma) - free_dma(dev->chanA.txdma); -fail: - free_irq(irq, dev); -fail1: - free_netdev(sv->netdev.dev); -fail2: + + z8530_describe(sv, "I/O", iobase); + sv->active = 1; + return sv; + +free_dma: + if (dma == 1) + free_dma(sv->chanA.rxdma); +err_rxdma: + if (dma) + free_dma(sv->chanA.txdma); +err_txdma: + free_irq(irq, sv); +err_irq: kfree(sv); -fail3: - release_region(iobase,8); +err_kzalloc: + release_region(iobase, 8); return NULL; } -static void sv11_shutdown(struct sv11_device *dev) +static void sv11_shutdown(struct z8530_dev *dev) { - sppp_detach(dev->netdev.dev); - unregister_netdev(dev->netdev.dev); - z8530_shutdown(&dev->sync); - free_irq(dev->sync.irq, dev); - if(dma) - { - if(dma==1) - free_dma(dev->sync.chanA.rxdma); - free_dma(dev->sync.chanA.txdma); + unregister_hdlc_device(dev->chanA.netdevice); + z8530_shutdown(dev); + free_irq(dev->irq, dev); + if (dma) { + if (dma == 1) + free_dma(dev->chanA.rxdma); + free_dma(dev->chanA.txdma); } - release_region(dev->sync.chanA.ctrlio-1, 8); - free_netdev(dev->netdev.dev); + release_region(dev->chanA.ctrlio - 1, 8); + free_netdev(dev->chanA.netdevice); kfree(dev); } -#ifdef MODULE - -static int io=0x200; -static int irq=9; +static int io = 0x200; +static int irq = 9; module_param(io, int, 0); MODULE_PARM_DESC(io, "The I/O base of the Comtrol Hostess SV11 card"); @@ -397,22 +336,17 @@ MODULE_AUTHOR("Alan Cox"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Modular driver for the Comtrol Hostess SV11"); -static struct sv11_device *sv11_unit; +static struct z8530_dev *sv11_unit; int init_module(void) { - printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.03.\n"); - printk(KERN_INFO "(c) Copyright 2001, Red Hat Inc.\n"); - if((sv11_unit=sv11_init(io,irq))==NULL) + if ((sv11_unit = sv11_init(io, irq)) == NULL) return -ENODEV; return 0; } void cleanup_module(void) { - if(sv11_unit) + if (sv11_unit) sv11_shutdown(sv11_unit); } - -#endif - diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c new file mode 100644 index 00000000000..e7bbdb7af53 --- /dev/null +++ b/drivers/net/wan/ixp4xx_hss.c @@ -0,0 +1,1419 @@ +/* + * Intel IXP4xx HSS (synchronous serial port) driver for Linux + * + * Copyright (C) 2007-2008 Krzysztof Hałasa <khc@pm.waw.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/bitops.h> +#include <linux/cdev.h> +#include <linux/dma-mapping.h> +#include <linux/dmapool.h> +#include <linux/fs.h> +#include <linux/hdlc.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/poll.h> +#include <linux/slab.h> +#include <mach/npe.h> +#include <mach/qmgr.h> + +#define DEBUG_DESC 0 +#define DEBUG_RX 0 +#define DEBUG_TX 0 +#define DEBUG_PKT_BYTES 0 +#define DEBUG_CLOSE 0 + +#define DRV_NAME "ixp4xx_hss" + +#define PKT_EXTRA_FLAGS 0 /* orig 1 */ +#define PKT_NUM_PIPES 1 /* 1, 2 or 4 */ +#define PKT_PIPE_FIFO_SIZEW 4 /* total 4 dwords per HSS */ + +#define RX_DESCS 16 /* also length of all RX queues */ +#define TX_DESCS 16 /* also length of all TX queues */ + +#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) +#define RX_SIZE (HDLC_MAX_MRU + 4) /* NPE needs more space */ +#define MAX_CLOSE_WAIT 1000 /* microseconds */ +#define HSS_COUNT 2 +#define FRAME_SIZE 256 /* doesn't matter at this point */ +#define FRAME_OFFSET 0 +#define MAX_CHANNELS (FRAME_SIZE / 8) + +#define NAPI_WEIGHT 16 + +/* Queue IDs */ +#define HSS0_CHL_RXTRIG_QUEUE 12 /* orig size = 32 dwords */ +#define HSS0_PKT_RX_QUEUE 13 /* orig size = 32 dwords */ +#define HSS0_PKT_TX0_QUEUE 14 /* orig size = 16 dwords */ +#define HSS0_PKT_TX1_QUEUE 15 +#define HSS0_PKT_TX2_QUEUE 16 +#define HSS0_PKT_TX3_QUEUE 17 +#define HSS0_PKT_RXFREE0_QUEUE 18 /* orig size = 16 dwords */ +#define HSS0_PKT_RXFREE1_QUEUE 19 +#define HSS0_PKT_RXFREE2_QUEUE 20 +#define HSS0_PKT_RXFREE3_QUEUE 21 +#define HSS0_PKT_TXDONE_QUEUE 22 /* orig size = 64 dwords */ + +#define HSS1_CHL_RXTRIG_QUEUE 10 +#define HSS1_PKT_RX_QUEUE 0 +#define HSS1_PKT_TX0_QUEUE 5 +#define HSS1_PKT_TX1_QUEUE 6 +#define HSS1_PKT_TX2_QUEUE 7 +#define HSS1_PKT_TX3_QUEUE 8 +#define HSS1_PKT_RXFREE0_QUEUE 1 +#define HSS1_PKT_RXFREE1_QUEUE 2 +#define HSS1_PKT_RXFREE2_QUEUE 3 +#define HSS1_PKT_RXFREE3_QUEUE 4 +#define HSS1_PKT_TXDONE_QUEUE 9 + +#define NPE_PKT_MODE_HDLC 0 +#define NPE_PKT_MODE_RAW 1 +#define NPE_PKT_MODE_56KMODE 2 +#define NPE_PKT_MODE_56KENDIAN_MSB 4 + +/* PKT_PIPE_HDLC_CFG_WRITE flags */ +#define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */ +#define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */ +#define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */ + + +/* hss_config, PCRs */ +/* Frame sync sampling, default = active low */ +#define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000 +#define PCR_FRM_SYNC_FALLINGEDGE 0x80000000 +#define PCR_FRM_SYNC_RISINGEDGE 0xC0000000 + +/* Frame sync pin: input (default) or output generated off a given clk edge */ +#define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000 +#define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000 + +/* Frame and data clock sampling on edge, default = falling */ +#define PCR_FCLK_EDGE_RISING 0x08000000 +#define PCR_DCLK_EDGE_RISING 0x04000000 + +/* Clock direction, default = input */ +#define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000 + +/* Generate/Receive frame pulses, default = enabled */ +#define PCR_FRM_PULSE_DISABLED 0x01000000 + + /* Data rate is full (default) or half the configured clk speed */ +#define PCR_HALF_CLK_RATE 0x00200000 + +/* Invert data between NPE and HSS FIFOs? (default = no) */ +#define PCR_DATA_POLARITY_INVERT 0x00100000 + +/* TX/RX endianness, default = LSB */ +#define PCR_MSB_ENDIAN 0x00080000 + +/* Normal (default) / open drain mode (TX only) */ +#define PCR_TX_PINS_OPEN_DRAIN 0x00040000 + +/* No framing bit transmitted and expected on RX? (default = framing bit) */ +#define PCR_SOF_NO_FBIT 0x00020000 + +/* Drive data pins? */ +#define PCR_TX_DATA_ENABLE 0x00010000 + +/* Voice 56k type: drive the data pins low (default), high, high Z */ +#define PCR_TX_V56K_HIGH 0x00002000 +#define PCR_TX_V56K_HIGH_IMP 0x00004000 + +/* Unassigned type: drive the data pins low (default), high, high Z */ +#define PCR_TX_UNASS_HIGH 0x00000800 +#define PCR_TX_UNASS_HIGH_IMP 0x00001000 + +/* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */ +#define PCR_TX_FB_HIGH_IMP 0x00000400 + +/* 56k data endiannes - which bit unused: high (default) or low */ +#define PCR_TX_56KE_BIT_0_UNUSED 0x00000200 + +/* 56k data transmission type: 32/8 bit data (default) or 56K data */ +#define PCR_TX_56KS_56K_DATA 0x00000100 + +/* hss_config, cCR */ +/* Number of packetized clients, default = 1 */ +#define CCR_NPE_HFIFO_2_HDLC 0x04000000 +#define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000 + +/* default = no loopback */ +#define CCR_LOOPBACK 0x02000000 + +/* HSS number, default = 0 (first) */ +#define CCR_SECOND_HSS 0x01000000 + + +/* hss_config, clkCR: main:10, num:10, denom:12 */ +#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/ + +#define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15) +#define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47) +#define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192) +#define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63) +#define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127) +#define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255) + +#define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127) +#define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383) +#define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385) +#define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511) +#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023) +#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047) + +/* + * HSS_CONFIG_CLOCK_CR register consists of 3 parts: + * A (10 bits), B (10 bits) and C (12 bits). + * IXP42x HSS clock generator operation (verified with an oscilloscope): + * Each clock bit takes 7.5 ns (1 / 133.xx MHz). + * The clock sequence consists of (C - B) states of 0s and 1s, each state is + * A bits wide. It's followed by (B + 1) states of 0s and 1s, each state is + * (A + 1) bits wide. + * + * The resulting average clock frequency (assuming 33.333 MHz oscillator) is: + * freq = 66.666 MHz / (A + (B + 1) / (C + 1)) + * minimum freq = 66.666 MHz / (A + 1) + * maximum freq = 66.666 MHz / A + * + * Example: A = 2, B = 2, C = 7, CLOCK_CR register = 2 << 22 | 2 << 12 | 7 + * freq = 66.666 MHz / (2 + (2 + 1) / (7 + 1)) = 28.07 MHz (Mb/s). + * The clock sequence is: 1100110011 (5 doubles) 000111000 (3 triples). + * The sequence takes (C - B) * A + (B + 1) * (A + 1) = 5 * 2 + 3 * 3 bits + * = 19 bits (each 7.5 ns long) = 142.5 ns (then the sequence repeats). + * The sequence consists of 4 complete clock periods, thus the average + * frequency (= clock rate) is 4 / 142.5 ns = 28.07 MHz (Mb/s). + * (max specified clock rate for IXP42x HSS is 8.192 Mb/s). + */ + +/* hss_config, LUT entries */ +#define TDMMAP_UNASSIGNED 0 +#define TDMMAP_HDLC 1 /* HDLC - packetized */ +#define TDMMAP_VOICE56K 2 /* Voice56K - 7-bit channelized */ +#define TDMMAP_VOICE64K 3 /* Voice64K - 8-bit channelized */ + +/* offsets into HSS config */ +#define HSS_CONFIG_TX_PCR 0x00 /* port configuration registers */ +#define HSS_CONFIG_RX_PCR 0x04 +#define HSS_CONFIG_CORE_CR 0x08 /* loopback control, HSS# */ +#define HSS_CONFIG_CLOCK_CR 0x0C /* clock generator control */ +#define HSS_CONFIG_TX_FCR 0x10 /* frame configuration registers */ +#define HSS_CONFIG_RX_FCR 0x14 +#define HSS_CONFIG_TX_LUT 0x18 /* channel look-up tables */ +#define HSS_CONFIG_RX_LUT 0x38 + + +/* NPE command codes */ +/* writes the ConfigWord value to the location specified by offset */ +#define PORT_CONFIG_WRITE 0x40 + +/* triggers the NPE to load the contents of the configuration table */ +#define PORT_CONFIG_LOAD 0x41 + +/* triggers the NPE to return an HssErrorReadResponse message */ +#define PORT_ERROR_READ 0x42 + +/* triggers the NPE to reset internal status and enable the HssPacketized + operation for the flow specified by pPipe */ +#define PKT_PIPE_FLOW_ENABLE 0x50 +#define PKT_PIPE_FLOW_DISABLE 0x51 +#define PKT_NUM_PIPES_WRITE 0x52 +#define PKT_PIPE_FIFO_SIZEW_WRITE 0x53 +#define PKT_PIPE_HDLC_CFG_WRITE 0x54 +#define PKT_PIPE_IDLE_PATTERN_WRITE 0x55 +#define PKT_PIPE_RX_SIZE_WRITE 0x56 +#define PKT_PIPE_MODE_WRITE 0x57 + +/* HDLC packet status values - desc->status */ +#define ERR_SHUTDOWN 1 /* stop or shutdown occurrence */ +#define ERR_HDLC_ALIGN 2 /* HDLC alignment error */ +#define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */ +#define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving + this packet (if buf_len < pkt_len) */ +#define ERR_HDLC_TOO_LONG 5 /* HDLC frame size too long */ +#define ERR_HDLC_ABORT 6 /* abort sequence received */ +#define ERR_DISCONNECTING 7 /* disconnect is in progress */ + + +#ifdef __ARMEB__ +typedef struct sk_buff buffer_t; +#define free_buffer dev_kfree_skb +#define free_buffer_irq dev_kfree_skb_irq +#else +typedef void buffer_t; +#define free_buffer kfree +#define free_buffer_irq kfree +#endif + +struct port { + struct device *dev; + struct npe *npe; + struct net_device *netdev; + struct napi_struct napi; + struct hss_plat_info *plat; + buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; + struct desc *desc_tab; /* coherent */ + u32 desc_tab_phys; + unsigned int id; + unsigned int clock_type, clock_rate, loopback; + unsigned int initialized, carrier; + u8 hdlc_cfg; + u32 clock_reg; +}; + +/* NPE message structure */ +struct msg { +#ifdef __ARMEB__ + u8 cmd, unused, hss_port, index; + union { + struct { u8 data8a, data8b, data8c, data8d; }; + struct { u16 data16a, data16b; }; + struct { u32 data32; }; + }; +#else + u8 index, hss_port, unused, cmd; + union { + struct { u8 data8d, data8c, data8b, data8a; }; + struct { u16 data16b, data16a; }; + struct { u32 data32; }; + }; +#endif +}; + +/* HDLC packet descriptor */ +struct desc { + u32 next; /* pointer to next buffer, unused */ + +#ifdef __ARMEB__ + u16 buf_len; /* buffer length */ + u16 pkt_len; /* packet length */ + u32 data; /* pointer to data buffer in RAM */ + u8 status; + u8 error_count; + u16 __reserved; +#else + u16 pkt_len; /* packet length */ + u16 buf_len; /* buffer length */ + u32 data; /* pointer to data buffer in RAM */ + u16 __reserved; + u8 error_count; + u8 status; +#endif + u32 __reserved1[4]; +}; + + +#define rx_desc_phys(port, n) ((port)->desc_tab_phys + \ + (n) * sizeof(struct desc)) +#define rx_desc_ptr(port, n) (&(port)->desc_tab[n]) + +#define tx_desc_phys(port, n) ((port)->desc_tab_phys + \ + ((n) + RX_DESCS) * sizeof(struct desc)) +#define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS]) + +/***************************************************************************** + * global variables + ****************************************************************************/ + +static int ports_open; +static struct dma_pool *dma_pool; +static spinlock_t npe_lock; + +static const struct { + int tx, txdone, rx, rxfree; +}queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE, + HSS0_PKT_RXFREE0_QUEUE}, + {HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE, + HSS1_PKT_RXFREE0_QUEUE}, +}; + +/***************************************************************************** + * utility functions + ****************************************************************************/ + +static inline struct port* dev_to_port(struct net_device *dev) +{ + return dev_to_hdlc(dev)->priv; +} + +#ifndef __ARMEB__ +static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) +{ + int i; + for (i = 0; i < cnt; i++) + dest[i] = swab32(src[i]); +} +#endif + +/***************************************************************************** + * HSS access + ****************************************************************************/ + +static void hss_npe_send(struct port *port, struct msg *msg, const char* what) +{ + u32 *val = (u32*)msg; + if (npe_send_message(port->npe, msg, what)) { + pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n", + port->id, val[0], val[1], npe_name(port->npe)); + BUG(); + } +} + +static void hss_config_set_lut(struct port *port) +{ + struct msg msg; + int ch; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + + for (ch = 0; ch < MAX_CHANNELS; ch++) { + msg.data32 >>= 2; + msg.data32 |= TDMMAP_HDLC << 30; + + if (ch % 16 == 15) { + msg.index = HSS_CONFIG_TX_LUT + ((ch / 4) & ~3); + hss_npe_send(port, &msg, "HSS_SET_TX_LUT"); + + msg.index += HSS_CONFIG_RX_LUT - HSS_CONFIG_TX_LUT; + hss_npe_send(port, &msg, "HSS_SET_RX_LUT"); + } + } +} + +static void hss_config(struct port *port) +{ + struct msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + msg.index = HSS_CONFIG_TX_PCR; + msg.data32 = PCR_FRM_PULSE_DISABLED | PCR_MSB_ENDIAN | + PCR_TX_DATA_ENABLE | PCR_SOF_NO_FBIT; + if (port->clock_type == CLOCK_INT) + msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT; + hss_npe_send(port, &msg, "HSS_SET_TX_PCR"); + + msg.index = HSS_CONFIG_RX_PCR; + msg.data32 ^= PCR_TX_DATA_ENABLE | PCR_DCLK_EDGE_RISING; + hss_npe_send(port, &msg, "HSS_SET_RX_PCR"); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + msg.index = HSS_CONFIG_CORE_CR; + msg.data32 = (port->loopback ? CCR_LOOPBACK : 0) | + (port->id ? CCR_SECOND_HSS : 0); + hss_npe_send(port, &msg, "HSS_SET_CORE_CR"); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + msg.index = HSS_CONFIG_CLOCK_CR; + msg.data32 = port->clock_reg; + hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR"); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + msg.index = HSS_CONFIG_TX_FCR; + msg.data16a = FRAME_OFFSET; + msg.data16b = FRAME_SIZE - 1; + hss_npe_send(port, &msg, "HSS_SET_TX_FCR"); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_WRITE; + msg.hss_port = port->id; + msg.index = HSS_CONFIG_RX_FCR; + msg.data16a = FRAME_OFFSET; + msg.data16b = FRAME_SIZE - 1; + hss_npe_send(port, &msg, "HSS_SET_RX_FCR"); + + hss_config_set_lut(port); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_CONFIG_LOAD; + msg.hss_port = port->id; + hss_npe_send(port, &msg, "HSS_LOAD_CONFIG"); + + if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") || + /* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */ + msg.cmd != PORT_CONFIG_LOAD || msg.data32) { + pr_crit("HSS-%i: HSS_LOAD_CONFIG failed\n", port->id); + BUG(); + } + + /* HDLC may stop working without this - check FIXME */ + npe_recv_message(port->npe, &msg, "FLUSH_IT"); +} + +static void hss_set_hdlc_cfg(struct port *port) +{ + struct msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PKT_PIPE_HDLC_CFG_WRITE; + msg.hss_port = port->id; + msg.data8a = port->hdlc_cfg; /* rx_cfg */ + msg.data8b = port->hdlc_cfg | (PKT_EXTRA_FLAGS << 3); /* tx_cfg */ + hss_npe_send(port, &msg, "HSS_SET_HDLC_CFG"); +} + +static u32 hss_get_status(struct port *port) +{ + struct msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PORT_ERROR_READ; + msg.hss_port = port->id; + hss_npe_send(port, &msg, "PORT_ERROR_READ"); + if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) { + pr_crit("HSS-%i: unable to read HSS status\n", port->id); + BUG(); + } + + return msg.data32; +} + +static void hss_start_hdlc(struct port *port) +{ + struct msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PKT_PIPE_FLOW_ENABLE; + msg.hss_port = port->id; + msg.data32 = 0; + hss_npe_send(port, &msg, "HSS_ENABLE_PKT_PIPE"); +} + +static void hss_stop_hdlc(struct port *port) +{ + struct msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PKT_PIPE_FLOW_DISABLE; + msg.hss_port = port->id; + hss_npe_send(port, &msg, "HSS_DISABLE_PKT_PIPE"); + hss_get_status(port); /* make sure it's halted */ +} + +static int hss_load_firmware(struct port *port) +{ + struct msg msg; + int err; + + if (port->initialized) + return 0; + + if (!npe_running(port->npe) && + (err = npe_load_firmware(port->npe, npe_name(port->npe), + port->dev))) + return err; + + /* HDLC mode configuration */ + memset(&msg, 0, sizeof(msg)); + msg.cmd = PKT_NUM_PIPES_WRITE; + msg.hss_port = port->id; + msg.data8a = PKT_NUM_PIPES; + hss_npe_send(port, &msg, "HSS_SET_PKT_PIPES"); + + msg.cmd = PKT_PIPE_FIFO_SIZEW_WRITE; + msg.data8a = PKT_PIPE_FIFO_SIZEW; + hss_npe_send(port, &msg, "HSS_SET_PKT_FIFO"); + + msg.cmd = PKT_PIPE_MODE_WRITE; + msg.data8a = NPE_PKT_MODE_HDLC; + /* msg.data8b = inv_mask */ + /* msg.data8c = or_mask */ + hss_npe_send(port, &msg, "HSS_SET_PKT_MODE"); + + msg.cmd = PKT_PIPE_RX_SIZE_WRITE; + msg.data16a = HDLC_MAX_MRU; /* including CRC */ + hss_npe_send(port, &msg, "HSS_SET_PKT_RX_SIZE"); + + msg.cmd = PKT_PIPE_IDLE_PATTERN_WRITE; + msg.data32 = 0x7F7F7F7F; /* ??? FIXME */ + hss_npe_send(port, &msg, "HSS_SET_PKT_IDLE"); + + port->initialized = 1; + return 0; +} + +/***************************************************************************** + * packetized (HDLC) operation + ****************************************************************************/ + +static inline void debug_pkt(struct net_device *dev, const char *func, + u8 *data, int len) +{ +#if DEBUG_PKT_BYTES + int i; + + printk(KERN_DEBUG "%s: %s(%i)", dev->name, func, len); + for (i = 0; i < len; i++) { + if (i >= DEBUG_PKT_BYTES) + break; + printk("%s%02X", !(i % 4) ? " " : "", data[i]); + } + printk("\n"); +#endif +} + + +static inline void debug_desc(u32 phys, struct desc *desc) +{ +#if DEBUG_DESC + printk(KERN_DEBUG "%X: %X %3X %3X %08X %X %X\n", + phys, desc->next, desc->buf_len, desc->pkt_len, + desc->data, desc->status, desc->error_count); +#endif +} + +static inline int queue_get_desc(unsigned int queue, struct port *port, + int is_tx) +{ + u32 phys, tab_phys, n_desc; + struct desc *tab; + + if (!(phys = qmgr_get_entry(queue))) + return -1; + + BUG_ON(phys & 0x1F); + tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0); + tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0); + n_desc = (phys - tab_phys) / sizeof(struct desc); + BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS)); + debug_desc(phys, &tab[n_desc]); + BUG_ON(tab[n_desc].next); + return n_desc; +} + +static inline void queue_put_desc(unsigned int queue, u32 phys, + struct desc *desc) +{ + debug_desc(phys, desc); + BUG_ON(phys & 0x1F); + qmgr_put_entry(queue, phys); + /* Don't check for queue overflow here, we've allocated sufficient + length and queues >= 32 don't support this check anyway. */ +} + + +static inline void dma_unmap_tx(struct port *port, struct desc *desc) +{ +#ifdef __ARMEB__ + dma_unmap_single(&port->netdev->dev, desc->data, + desc->buf_len, DMA_TO_DEVICE); +#else + dma_unmap_single(&port->netdev->dev, desc->data & ~3, + ALIGN((desc->data & 3) + desc->buf_len, 4), + DMA_TO_DEVICE); +#endif +} + + +static void hss_hdlc_set_carrier(void *pdev, int carrier) +{ + struct net_device *netdev = pdev; + struct port *port = dev_to_port(netdev); + unsigned long flags; + + spin_lock_irqsave(&npe_lock, flags); + port->carrier = carrier; + if (!port->loopback) { + if (carrier) + netif_carrier_on(netdev); + else + netif_carrier_off(netdev); + } + spin_unlock_irqrestore(&npe_lock, flags); +} + +static void hss_hdlc_rx_irq(void *pdev) +{ + struct net_device *dev = pdev; + struct port *port = dev_to_port(dev); + +#if DEBUG_RX + printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); +#endif + qmgr_disable_irq(queue_ids[port->id].rx); + napi_schedule(&port->napi); +} + +static int hss_hdlc_poll(struct napi_struct *napi, int budget) +{ + struct port *port = container_of(napi, struct port, napi); + struct net_device *dev = port->netdev; + unsigned int rxq = queue_ids[port->id].rx; + unsigned int rxfreeq = queue_ids[port->id].rxfree; + int received = 0; + +#if DEBUG_RX + printk(KERN_DEBUG "%s: hss_hdlc_poll\n", dev->name); +#endif + + while (received < budget) { + struct sk_buff *skb; + struct desc *desc; + int n; +#ifdef __ARMEB__ + struct sk_buff *temp; + u32 phys; +#endif + + if ((n = queue_get_desc(rxq, port, 0)) < 0) { +#if DEBUG_RX + printk(KERN_DEBUG "%s: hss_hdlc_poll" + " napi_complete\n", dev->name); +#endif + napi_complete(napi); + qmgr_enable_irq(rxq); + if (!qmgr_stat_empty(rxq) && + napi_reschedule(napi)) { +#if DEBUG_RX + printk(KERN_DEBUG "%s: hss_hdlc_poll" + " napi_reschedule succeeded\n", + dev->name); +#endif + qmgr_disable_irq(rxq); + continue; + } +#if DEBUG_RX + printk(KERN_DEBUG "%s: hss_hdlc_poll all done\n", + dev->name); +#endif + return received; /* all work done */ + } + + desc = rx_desc_ptr(port, n); +#if 0 /* FIXME - error_count counts modulo 256, perhaps we should use it */ + if (desc->error_count) + printk(KERN_DEBUG "%s: hss_hdlc_poll status 0x%02X" + " errors %u\n", dev->name, desc->status, + desc->error_count); +#endif + skb = NULL; + switch (desc->status) { + case 0: +#ifdef __ARMEB__ + if ((skb = netdev_alloc_skb(dev, RX_SIZE)) != NULL) { + phys = dma_map_single(&dev->dev, skb->data, + RX_SIZE, + DMA_FROM_DEVICE); + if (dma_mapping_error(&dev->dev, phys)) { + dev_kfree_skb(skb); + skb = NULL; + } + } +#else + skb = netdev_alloc_skb(dev, desc->pkt_len); +#endif + if (!skb) + dev->stats.rx_dropped++; + break; + case ERR_HDLC_ALIGN: + case ERR_HDLC_ABORT: + dev->stats.rx_frame_errors++; + dev->stats.rx_errors++; + break; + case ERR_HDLC_FCS: + dev->stats.rx_crc_errors++; + dev->stats.rx_errors++; + break; + case ERR_HDLC_TOO_LONG: + dev->stats.rx_length_errors++; + dev->stats.rx_errors++; + break; + default: /* FIXME - remove printk */ + netdev_err(dev, "hss_hdlc_poll: status 0x%02X errors %u\n", + desc->status, desc->error_count); + dev->stats.rx_errors++; + } + + if (!skb) { + /* put the desc back on RX-ready queue */ + desc->buf_len = RX_SIZE; + desc->pkt_len = desc->status = 0; + queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); + continue; + } + + /* process received frame */ +#ifdef __ARMEB__ + temp = skb; + skb = port->rx_buff_tab[n]; + dma_unmap_single(&dev->dev, desc->data, + RX_SIZE, DMA_FROM_DEVICE); +#else + dma_sync_single_for_cpu(&dev->dev, desc->data, + RX_SIZE, DMA_FROM_DEVICE); + memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], + ALIGN(desc->pkt_len, 4) / 4); +#endif + skb_put(skb, desc->pkt_len); + + debug_pkt(dev, "hss_hdlc_poll", skb->data, skb->len); + + skb->protocol = hdlc_type_trans(skb, dev); + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + netif_receive_skb(skb); + + /* put the new buffer on RX-free queue */ +#ifdef __ARMEB__ + port->rx_buff_tab[n] = temp; + desc->data = phys; +#endif + desc->buf_len = RX_SIZE; + desc->pkt_len = 0; + queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); + received++; + } +#if DEBUG_RX + printk(KERN_DEBUG "hss_hdlc_poll: end, not all work done\n"); +#endif + return received; /* not all work done */ +} + + +static void hss_hdlc_txdone_irq(void *pdev) +{ + struct net_device *dev = pdev; + struct port *port = dev_to_port(dev); + int n_desc; + +#if DEBUG_TX + printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n"); +#endif + while ((n_desc = queue_get_desc(queue_ids[port->id].txdone, + port, 1)) >= 0) { + struct desc *desc; + int start; + + desc = tx_desc_ptr(port, n_desc); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += desc->pkt_len; + + dma_unmap_tx(port, desc); +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n", + dev->name, port->tx_buff_tab[n_desc]); +#endif + free_buffer_irq(port->tx_buff_tab[n_desc]); + port->tx_buff_tab[n_desc] = NULL; + + start = qmgr_stat_below_low_watermark(port->plat->txreadyq); + queue_put_desc(port->plat->txreadyq, + tx_desc_phys(port, n_desc), desc); + if (start) { /* TX-ready queue was empty */ +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" + " ready\n", dev->name); +#endif + netif_wake_queue(dev); + } + } +} + +static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct port *port = dev_to_port(dev); + unsigned int txreadyq = port->plat->txreadyq; + int len, offset, bytes, n; + void *mem; + u32 phys; + struct desc *desc; + +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_xmit\n", dev->name); +#endif + + if (unlikely(skb->len > HDLC_MAX_MRU)) { + dev_kfree_skb(skb); + dev->stats.tx_errors++; + return NETDEV_TX_OK; + } + + debug_pkt(dev, "hss_hdlc_xmit", skb->data, skb->len); + + len = skb->len; +#ifdef __ARMEB__ + offset = 0; /* no need to keep alignment */ + bytes = len; + mem = skb->data; +#else + offset = (int)skb->data & 3; /* keep 32-bit alignment */ + bytes = ALIGN(offset + len, 4); + if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { + dev_kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); + dev_kfree_skb(skb); +#endif + + phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); + if (dma_mapping_error(&dev->dev, phys)) { +#ifdef __ARMEB__ + dev_kfree_skb(skb); +#else + kfree(mem); +#endif + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + + n = queue_get_desc(txreadyq, port, 1); + BUG_ON(n < 0); + desc = tx_desc_ptr(port, n); + +#ifdef __ARMEB__ + port->tx_buff_tab[n] = skb; +#else + port->tx_buff_tab[n] = mem; +#endif + desc->data = phys + offset; + desc->buf_len = desc->pkt_len = len; + + wmb(); + queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); + + if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); +#endif + netif_stop_queue(dev); + /* we could miss TX ready interrupt */ + if (!qmgr_stat_below_low_watermark(txreadyq)) { +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", + dev->name); +#endif + netif_wake_queue(dev); + } + } + +#if DEBUG_TX + printk(KERN_DEBUG "%s: hss_hdlc_xmit end\n", dev->name); +#endif + return NETDEV_TX_OK; +} + + +static int request_hdlc_queues(struct port *port) +{ + int err; + + err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0, + "%s:RX-free", port->netdev->name); + if (err) + return err; + + err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0, + "%s:RX", port->netdev->name); + if (err) + goto rel_rxfree; + + err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0, + "%s:TX", port->netdev->name); + if (err) + goto rel_rx; + + err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, + "%s:TX-ready", port->netdev->name); + if (err) + goto rel_tx; + + err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0, + "%s:TX-done", port->netdev->name); + if (err) + goto rel_txready; + return 0; + +rel_txready: + qmgr_release_queue(port->plat->txreadyq); +rel_tx: + qmgr_release_queue(queue_ids[port->id].tx); +rel_rx: + qmgr_release_queue(queue_ids[port->id].rx); +rel_rxfree: + qmgr_release_queue(queue_ids[port->id].rxfree); + printk(KERN_DEBUG "%s: unable to request hardware queues\n", + port->netdev->name); + return err; +} + +static void release_hdlc_queues(struct port *port) +{ + qmgr_release_queue(queue_ids[port->id].rxfree); + qmgr_release_queue(queue_ids[port->id].rx); + qmgr_release_queue(queue_ids[port->id].txdone); + qmgr_release_queue(queue_ids[port->id].tx); + qmgr_release_queue(port->plat->txreadyq); +} + +static int init_hdlc_queues(struct port *port) +{ + int i; + + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) + return -ENOMEM; + } + + if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, + &port->desc_tab_phys))) + return -ENOMEM; + memset(port->desc_tab, 0, POOL_ALLOC_SIZE); + memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */ + memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab)); + + /* Setup RX buffers */ + for (i = 0; i < RX_DESCS; i++) { + struct desc *desc = rx_desc_ptr(port, i); + buffer_t *buff; + void *data; +#ifdef __ARMEB__ + if (!(buff = netdev_alloc_skb(port->netdev, RX_SIZE))) + return -ENOMEM; + data = buff->data; +#else + if (!(buff = kmalloc(RX_SIZE, GFP_KERNEL))) + return -ENOMEM; + data = buff; +#endif + desc->buf_len = RX_SIZE; + desc->data = dma_map_single(&port->netdev->dev, data, + RX_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(&port->netdev->dev, desc->data)) { + free_buffer(buff); + return -EIO; + } + port->rx_buff_tab[i] = buff; + } + + return 0; +} + +static void destroy_hdlc_queues(struct port *port) +{ + int i; + + if (port->desc_tab) { + for (i = 0; i < RX_DESCS; i++) { + struct desc *desc = rx_desc_ptr(port, i); + buffer_t *buff = port->rx_buff_tab[i]; + if (buff) { + dma_unmap_single(&port->netdev->dev, + desc->data, RX_SIZE, + DMA_FROM_DEVICE); + free_buffer(buff); + } + } + for (i = 0; i < TX_DESCS; i++) { + struct desc *desc = tx_desc_ptr(port, i); + buffer_t *buff = port->tx_buff_tab[i]; + if (buff) { + dma_unmap_tx(port, desc); + free_buffer(buff); + } + } + dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys); + port->desc_tab = NULL; + } + + if (!ports_open && dma_pool) { + dma_pool_destroy(dma_pool); + dma_pool = NULL; + } +} + +static int hss_hdlc_open(struct net_device *dev) +{ + struct port *port = dev_to_port(dev); + unsigned long flags; + int i, err = 0; + + if ((err = hdlc_open(dev))) + return err; + + if ((err = hss_load_firmware(port))) + goto err_hdlc_close; + + if ((err = request_hdlc_queues(port))) + goto err_hdlc_close; + + if ((err = init_hdlc_queues(port))) + goto err_destroy_queues; + + spin_lock_irqsave(&npe_lock, flags); + if (port->plat->open) + if ((err = port->plat->open(port->id, dev, + hss_hdlc_set_carrier))) + goto err_unlock; + spin_unlock_irqrestore(&npe_lock, flags); + + /* Populate queues with buffers, no failure after this point */ + for (i = 0; i < TX_DESCS; i++) + queue_put_desc(port->plat->txreadyq, + tx_desc_phys(port, i), tx_desc_ptr(port, i)); + + for (i = 0; i < RX_DESCS; i++) + queue_put_desc(queue_ids[port->id].rxfree, + rx_desc_phys(port, i), rx_desc_ptr(port, i)); + + napi_enable(&port->napi); + netif_start_queue(dev); + + qmgr_set_irq(queue_ids[port->id].rx, QUEUE_IRQ_SRC_NOT_EMPTY, + hss_hdlc_rx_irq, dev); + + qmgr_set_irq(queue_ids[port->id].txdone, QUEUE_IRQ_SRC_NOT_EMPTY, + hss_hdlc_txdone_irq, dev); + qmgr_enable_irq(queue_ids[port->id].txdone); + + ports_open++; + + hss_set_hdlc_cfg(port); + hss_config(port); + + hss_start_hdlc(port); + + /* we may already have RX data, enables IRQ */ + napi_schedule(&port->napi); + return 0; + +err_unlock: + spin_unlock_irqrestore(&npe_lock, flags); +err_destroy_queues: + destroy_hdlc_queues(port); + release_hdlc_queues(port); +err_hdlc_close: + hdlc_close(dev); + return err; +} + +static int hss_hdlc_close(struct net_device *dev) +{ + struct port *port = dev_to_port(dev); + unsigned long flags; + int i, buffs = RX_DESCS; /* allocated RX buffers */ + + spin_lock_irqsave(&npe_lock, flags); + ports_open--; + qmgr_disable_irq(queue_ids[port->id].rx); + netif_stop_queue(dev); + napi_disable(&port->napi); + + hss_stop_hdlc(port); + + while (queue_get_desc(queue_ids[port->id].rxfree, port, 0) >= 0) + buffs--; + while (queue_get_desc(queue_ids[port->id].rx, port, 0) >= 0) + buffs--; + + if (buffs) + netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n", + buffs); + + buffs = TX_DESCS; + while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0) + buffs--; /* cancel TX */ + + i = 0; + do { + while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) + buffs--; + if (!buffs) + break; + } while (++i < MAX_CLOSE_WAIT); + + if (buffs) + netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n", + buffs); +#if DEBUG_CLOSE + if (!buffs) + printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); +#endif + qmgr_disable_irq(queue_ids[port->id].txdone); + + if (port->plat->close) + port->plat->close(port->id, dev); + spin_unlock_irqrestore(&npe_lock, flags); + + destroy_hdlc_queues(port); + release_hdlc_queues(port); + hdlc_close(dev); + return 0; +} + + +static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +{ + struct port *port = dev_to_port(dev); + + if (encoding != ENCODING_NRZ) + return -EINVAL; + + switch(parity) { + case PARITY_CRC16_PR1_CCITT: + port->hdlc_cfg = 0; + return 0; + + case PARITY_CRC32_PR1_CCITT: + port->hdlc_cfg = PKT_HDLC_CRC_32; + return 0; + + default: + return -EINVAL; + } +} + +static u32 check_clock(u32 rate, u32 a, u32 b, u32 c, + u32 *best, u32 *best_diff, u32 *reg) +{ + /* a is 10-bit, b is 10-bit, c is 12-bit */ + u64 new_rate; + u32 new_diff; + + new_rate = ixp4xx_timer_freq * (u64)(c + 1); + do_div(new_rate, a * (c + 1) + b + 1); + new_diff = abs((u32)new_rate - rate); + + if (new_diff < *best_diff) { + *best = new_rate; + *best_diff = new_diff; + *reg = (a << 22) | (b << 12) | c; + } + return new_diff; +} + +static void find_best_clock(u32 rate, u32 *best, u32 *reg) +{ + u32 a, b, diff = 0xFFFFFFFF; + + a = ixp4xx_timer_freq / rate; + + if (a > 0x3FF) { /* 10-bit value - we can go as slow as ca. 65 kb/s */ + check_clock(rate, 0x3FF, 1, 1, best, &diff, reg); + return; + } + if (a == 0) { /* > 66.666 MHz */ + a = 1; /* minimum divider is 1 (a = 0, b = 1, c = 1) */ + rate = ixp4xx_timer_freq; + } + + if (rate * a == ixp4xx_timer_freq) { /* don't divide by 0 later */ + check_clock(rate, a - 1, 1, 1, best, &diff, reg); + return; + } + + for (b = 0; b < 0x400; b++) { + u64 c = (b + 1) * (u64)rate; + do_div(c, ixp4xx_timer_freq - rate * a); + c--; + if (c >= 0xFFF) { /* 12-bit - no need to check more 'b's */ + if (b == 0 && /* also try a bit higher rate */ + !check_clock(rate, a - 1, 1, 1, best, &diff, reg)) + return; + check_clock(rate, a, b, 0xFFF, best, &diff, reg); + return; + } + if (!check_clock(rate, a, b, c, best, &diff, reg)) + return; + if (!check_clock(rate, a, b, c + 1, best, &diff, reg)) + return; + } +} + +static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + struct port *port = dev_to_port(dev); + unsigned long flags; + int clk; + + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); + + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: + ifr->ifr_settings.type = IF_IFACE_V35; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + memset(&new_line, 0, sizeof(new_line)); + new_line.clock_type = port->clock_type; + new_line.clock_rate = port->clock_rate; + new_line.loopback = port->loopback; + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: + case IF_IFACE_V35: + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + clk = new_line.clock_type; + if (port->plat->set_clock) + clk = port->plat->set_clock(port->id, clk); + + if (clk != CLOCK_EXT && clk != CLOCK_INT) + return -EINVAL; /* No such clock setting */ + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + port->clock_type = clk; /* Update settings */ + if (clk == CLOCK_INT) + find_best_clock(new_line.clock_rate, &port->clock_rate, + &port->clock_reg); + else { + port->clock_rate = 0; + port->clock_reg = CLK42X_SPEED_2048KHZ; + } + port->loopback = new_line.loopback; + + spin_lock_irqsave(&npe_lock, flags); + + if (dev->flags & IFF_UP) + hss_config(port); + + if (port->loopback || port->carrier) + netif_carrier_on(port->netdev); + else + netif_carrier_off(port->netdev); + spin_unlock_irqrestore(&npe_lock, flags); + + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } +} + +/***************************************************************************** + * initialization + ****************************************************************************/ + +static const struct net_device_ops hss_hdlc_ops = { + .ndo_open = hss_hdlc_open, + .ndo_stop = hss_hdlc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hss_hdlc_ioctl, +}; + +static int hss_init_one(struct platform_device *pdev) +{ + struct port *port; + struct net_device *dev; + hdlc_device *hdlc; + int err; + + if ((port = kzalloc(sizeof(*port), GFP_KERNEL)) == NULL) + return -ENOMEM; + + if ((port->npe = npe_request(0)) == NULL) { + err = -ENODEV; + goto err_free; + } + + if ((port->netdev = dev = alloc_hdlcdev(port)) == NULL) { + err = -ENOMEM; + goto err_plat; + } + + SET_NETDEV_DEV(dev, &pdev->dev); + hdlc = dev_to_hdlc(dev); + hdlc->attach = hss_hdlc_attach; + hdlc->xmit = hss_hdlc_xmit; + dev->netdev_ops = &hss_hdlc_ops; + dev->tx_queue_len = 100; + port->clock_type = CLOCK_EXT; + port->clock_rate = 0; + port->clock_reg = CLK42X_SPEED_2048KHZ; + port->id = pdev->id; + port->dev = &pdev->dev; + port->plat = pdev->dev.platform_data; + netif_napi_add(dev, &port->napi, hss_hdlc_poll, NAPI_WEIGHT); + + if ((err = register_hdlc_device(dev))) + goto err_free_netdev; + + platform_set_drvdata(pdev, port); + + netdev_info(dev, "initialized\n"); + return 0; + +err_free_netdev: + free_netdev(dev); +err_plat: + npe_release(port->npe); +err_free: + kfree(port); + return err; +} + +static int hss_remove_one(struct platform_device *pdev) +{ + struct port *port = platform_get_drvdata(pdev); + + unregister_hdlc_device(port->netdev); + free_netdev(port->netdev); + npe_release(port->npe); + kfree(port); + return 0; +} + +static struct platform_driver ixp4xx_hss_driver = { + .driver.name = DRV_NAME, + .probe = hss_init_one, + .remove = hss_remove_one, +}; + +static int __init hss_init_module(void) +{ + if ((ixp4xx_read_feature_bits() & + (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) != + (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) + return -ENODEV; + + spin_lock_init(&npe_lock); + + return platform_driver_register(&ixp4xx_hss_driver); +} + +static void __exit hss_cleanup_module(void) +{ + platform_driver_unregister(&ixp4xx_hss_driver); +} + +MODULE_AUTHOR("Krzysztof Halasa"); +MODULE_DESCRIPTION("Intel IXP4xx HSS driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:ixp4xx_hss"); +module_init(hss_init_module); +module_exit(hss_cleanup_module); diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 824df3b5ea4..a33a46fa88d 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -20,10 +20,13 @@ * 2000-11-14 Henner Eisen dev_hold/put, NETDEV_GOING_DOWN support */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/in.h> +#include <linux/slab.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/net.h> @@ -32,7 +35,6 @@ #include <linux/if_arp.h> #include <linux/skbuff.h> #include <net/sock.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <linux/mm.h> #include <linux/interrupt.h> @@ -45,7 +47,7 @@ #include <net/x25device.h> -static char bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* If this number is made larger, check that the temporary string buffer * in lapbeth_new_device is large enough to store the probe device name.*/ @@ -55,7 +57,6 @@ struct lapbethdev { struct list_head node; struct net_device *ethdev; /* link to ethernet device */ struct net_device *axdev; /* lapbeth device (lapb#) */ - struct net_device_stats stats; /* some statistics */ }; static LIST_HEAD(lapbeth_devices); @@ -91,7 +92,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe int len, err; struct lapbethdev *lapbeth; - if (dev->nd_net != &init_net) + if (dev_net(dev) != &init_net) goto drop; if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) @@ -107,10 +108,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe if (!netif_running(lapbeth->axdev)) goto drop_unlock; - lapbeth->stats.rx_packets++; - len = skb->data[0] + skb->data[1] * 256; - lapbeth->stats.rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; skb_pull(skb, 2); /* Remove the length bytes */ skb_trim(skb, len); /* Set the length of the data */ @@ -140,58 +140,50 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) return NET_RX_DROP; ptr = skb->data; - *ptr = 0x00; + *ptr = X25_IFACE_DATA; skb->protocol = x25_type_trans(skb, dev); - skb->dev->last_rx = jiffies; return netif_rx(skb); } /* * Send a LAPB frame via an ethernet interface */ -static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t lapbeth_xmit(struct sk_buff *skb, + struct net_device *dev) { - int err = -ENODEV; + int err; /* * Just to be *really* sure not to send anything if the interface * is down, the ethernet device may have gone. */ - if (!netif_running(dev)) { + if (!netif_running(dev)) goto drop; - } switch (skb->data[0]) { - case 0x00: - err = 0; + case X25_IFACE_DATA: break; - case 0x01: + case X25_IFACE_CONNECT: if ((err = lapb_connect_request(dev)) != LAPB_OK) - printk(KERN_ERR "lapbeth: lapb_connect_request " - "error: %d\n", err); - goto drop_ok; - case 0x02: + pr_err("lapb_connect_request error: %d\n", err); + goto drop; + case X25_IFACE_DISCONNECT: if ((err = lapb_disconnect_request(dev)) != LAPB_OK) - printk(KERN_ERR "lapbeth: lapb_disconnect_request " - "err: %d\n", err); + pr_err("lapb_disconnect_request err: %d\n", err); /* Fall thru */ default: - goto drop_ok; + goto drop; } skb_pull(skb, 1); if ((err = lapb_data_request(dev, skb)) != LAPB_OK) { - printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err); - err = -ENOMEM; + pr_err("lapb_data_request error - %d\n", err); goto drop; } - err = 0; out: - return err; -drop_ok: - err = 0; + return NETDEV_TX_OK; drop: kfree_skb(skb); goto out; @@ -211,8 +203,8 @@ static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb) *ptr++ = size % 256; *ptr++ = size / 256; - lapbeth->stats.tx_packets++; - lapbeth->stats.tx_bytes += size; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += size; skb->dev = dev = lapbeth->ethdev; @@ -227,15 +219,14 @@ static void lapbeth_connected(struct net_device *dev, int reason) struct sk_buff *skb = dev_alloc_skb(1); if (!skb) { - printk(KERN_ERR "lapbeth: out of memory\n"); + pr_err("out of memory\n"); return; } ptr = skb_put(skb, 1); - *ptr = 0x01; + *ptr = X25_IFACE_CONNECT; skb->protocol = x25_type_trans(skb, dev); - skb->dev->last_rx = jiffies; netif_rx(skb); } @@ -245,28 +236,18 @@ static void lapbeth_disconnected(struct net_device *dev, int reason) struct sk_buff *skb = dev_alloc_skb(1); if (!skb) { - printk(KERN_ERR "lapbeth: out of memory\n"); + pr_err("out of memory\n"); return; } ptr = skb_put(skb, 1); - *ptr = 0x02; + *ptr = X25_IFACE_DISCONNECT; skb->protocol = x25_type_trans(skb, dev); - skb->dev->last_rx = jiffies; netif_rx(skb); } /* - * Statistics - */ -static struct net_device_stats *lapbeth_get_stats(struct net_device *dev) -{ - struct lapbethdev *lapbeth = netdev_priv(dev); - return &lapbeth->stats; -} - -/* * Set AX.25 callsign */ static int lapbeth_set_mac_address(struct net_device *dev, void *addr) @@ -277,14 +258,13 @@ static int lapbeth_set_mac_address(struct net_device *dev, void *addr) } -static struct lapb_register_struct lapbeth_callbacks = { +static const struct lapb_register_struct lapbeth_callbacks = { .connect_confirmation = lapbeth_connected, .connect_indication = lapbeth_connected, .disconnect_confirmation = lapbeth_disconnected, .disconnect_indication = lapbeth_disconnected, .data_indication = lapbeth_data_indication, .data_transmit = lapbeth_data_transmit, - }; /* @@ -295,7 +275,7 @@ static int lapbeth_open(struct net_device *dev) int err; if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) { - printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err); + pr_err("lapb_register error: %d\n", err); return -ENODEV; } @@ -310,21 +290,24 @@ static int lapbeth_close(struct net_device *dev) netif_stop_queue(dev); if ((err = lapb_unregister(dev)) != LAPB_OK) - printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err); + pr_err("lapb_unregister error: %d\n", err); return 0; } /* ------------------------------------------------------------------------ */ +static const struct net_device_ops lapbeth_netdev_ops = { + .ndo_open = lapbeth_open, + .ndo_stop = lapbeth_close, + .ndo_start_xmit = lapbeth_xmit, + .ndo_set_mac_address = lapbeth_set_mac_address, +}; + static void lapbeth_setup(struct net_device *dev) { - dev->hard_start_xmit = lapbeth_xmit; - dev->open = lapbeth_open; - dev->stop = lapbeth_close; + dev->netdev_ops = &lapbeth_netdev_ops; dev->destructor = free_netdev; - dev->set_mac_address = lapbeth_set_mac_address; - dev->get_stats = lapbeth_get_stats; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; @@ -353,10 +336,6 @@ static int lapbeth_new_device(struct net_device *dev) dev_hold(dev); lapbeth->ethdev = dev; - rc = dev_alloc_name(ndev, ndev->name); - if (rc < 0) - goto fail; - rc = -EIO; if (register_netdevice(ndev)) goto fail; @@ -391,9 +370,9 @@ static int lapbeth_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct lapbethdev *lapbeth; - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); - if (dev->nd_net != &init_net) + if (dev_net(dev) != &init_net) return NOTIFY_DONE; if (!dev_is_ethdev(dev)) @@ -424,8 +403,8 @@ static int lapbeth_device_event(struct notifier_block *this, /* ------------------------------------------------------------------------ */ -static struct packet_type lapbeth_packet_type = { - .type = __constant_htons(ETH_P_DEC), +static struct packet_type lapbeth_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_DEC), .func = lapbeth_rcv, }; @@ -433,7 +412,8 @@ static struct notifier_block lapbeth_dev_notifier = { .notifier_call = lapbeth_device_event, }; -static char banner[] __initdata = KERN_INFO "LAPB Ethernet driver version 0.02\n"; +static const char banner[] __initconst = + KERN_INFO "LAPB Ethernet driver version 0.02\n"; static int __init lapbeth_init_driver(void) { @@ -459,6 +439,7 @@ static void __exit lapbeth_cleanup_driver(void) list_for_each_safe(entry, tmp, &lapbeth_devices) { lapbeth = list_entry(entry, struct lapbethdev, node); + dev_put(lapbeth->ethdev); unregister_netdevice(lapbeth->axdev); } rtnl_unlock(); diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile index dabdcfed4ef..609710d64eb 100644 --- a/drivers/net/wan/lmc/Makefile +++ b/drivers/net/wan/lmc/Makefile @@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o # -DDEBUG \ # -DLMC_PACKET_LOG -EXTRA_CFLAGS += -I. $(DBGDEF) +ccflags-y := -I. $(DBGDEF) diff --git a/drivers/net/wan/lmc/lmc.h b/drivers/net/wan/lmc/lmc.h index 882e58c1bfd..4ced7ac16c2 100644 --- a/drivers/net/wan/lmc/lmc.h +++ b/drivers/net/wan/lmc/lmc.h @@ -11,12 +11,12 @@ unsigned lmc_mii_readreg(lmc_softc_t * const sc, unsigned devaddr, unsigned regno); void lmc_mii_writereg(lmc_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data); -void lmc_led_on(lmc_softc_t * const, u_int32_t); -void lmc_led_off(lmc_softc_t * const, u_int32_t); +void lmc_led_on(lmc_softc_t * const, u32); +void lmc_led_off(lmc_softc_t * const, u32); unsigned lmc_mii_readreg(lmc_softc_t * const, unsigned, unsigned); void lmc_mii_writereg(lmc_softc_t * const, unsigned, unsigned, unsigned); -void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits); -void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits); +void lmc_gpio_mkinput(lmc_softc_t * const sc, u32 bits); +void lmc_gpio_mkoutput(lmc_softc_t * const sc, u32 bits); int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); @@ -26,8 +26,7 @@ extern lmc_media_t lmc_t1_media; extern lmc_media_t lmc_hssi_media; #ifdef _DBG_EVENTLOG -static void lmcEventLog( u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3 ); +static void lmcEventLog(u32 EventNum, u32 arg2, u32 arg3); #endif #endif - diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c index 3b94352b0d0..15049d711f4 100644 --- a/drivers/net/wan/lmc/lmc_debug.c +++ b/drivers/net/wan/lmc/lmc_debug.c @@ -1,4 +1,3 @@ - #include <linux/types.h> #include <linux/netdevice.h> #include <linux/interrupt.h> @@ -48,10 +47,10 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen) #endif #ifdef DEBUG -u_int32_t lmcEventLogIndex = 0; -u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS]; +u32 lmcEventLogIndex; +u32 lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS]; -void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3) +void lmcEventLog(u32 EventNum, u32 arg2, u32 arg3) { lmcEventLogBuf[lmcEventLogIndex++] = EventNum; lmcEventLogBuf[lmcEventLogIndex++] = arg2; diff --git a/drivers/net/wan/lmc/lmc_debug.h b/drivers/net/wan/lmc/lmc_debug.h index cf3563859bf..2d46f121549 100644 --- a/drivers/net/wan/lmc/lmc_debug.h +++ b/drivers/net/wan/lmc/lmc_debug.h @@ -38,15 +38,15 @@ #ifdef DEBUG -extern u_int32_t lmcEventLogIndex; -extern u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS]; +extern u32 lmcEventLogIndex; +extern u32 lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS]; #define LMC_EVENT_LOG(x, y, z) lmcEventLog((x), (y), (z)) #else #define LMC_EVENT_LOG(x,y,z) #endif /* end ifdef _DBG_EVENTLOG */ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen); -void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3); +void lmcEventLog(u32 EventNum, u32 arg2, u32 arg3); void lmc_trace(struct net_device *dev, char *msg); #endif diff --git a/drivers/net/wan/lmc/lmc_ioctl.h b/drivers/net/wan/lmc/lmc_ioctl.h index 57dd861cd3d..72fb113a44c 100644 --- a/drivers/net/wan/lmc/lmc_ioctl.h +++ b/drivers/net/wan/lmc/lmc_ioctl.h @@ -61,7 +61,7 @@ /* * IFTYPE defines */ -#define LMC_PPP 1 /* use sppp interface */ +#define LMC_PPP 1 /* use generic HDLC interface */ #define LMC_NET 2 /* use direct net interface */ #define LMC_RAW 3 /* use direct net interface */ diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 6635ecef36e..b2fe9bb8963 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 1997-2000 LAN Media Corporation (LMC) * All rights reserved. www.lanmedia.com + * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> * * This code is written by: * Andrew Stanley-Jones (asj@cban.com) @@ -23,7 +24,7 @@ * * Linux driver notes: * Linux uses the device struct lmc_private to pass private information - * arround. + * around. * * The initialization portion of this driver (the lmc_reset() and the * lmc_dec_reset() functions, as well as the led controls and the @@ -36,8 +37,6 @@ * */ -/* $Id: lmc_main.c,v 1.36 2000/04/11 05:25:25 asj Exp $ */ - #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> @@ -49,7 +48,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/delay.h> -#include <linux/init.h> +#include <linux/hdlc.h> #include <linux/in.h> #include <linux/if_arp.h> #include <linux/netdevice.h> @@ -57,9 +56,6 @@ #include <linux/skbuff.h> #include <linux/inet.h> #include <linux/bitops.h> - -#include <net/syncppp.h> - #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> #include <asm/dma.h> @@ -78,11 +74,9 @@ #include "lmc_debug.h" #include "lmc_proto.h" -static int lmc_first_load = 0; - static int LMC_PKT_BUF_SZ = 1542; -static struct pci_device_id lmc_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, PCI_VENDOR_ID_LMC, PCI_ANY_ID }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, @@ -91,11 +85,11 @@ static struct pci_device_id lmc_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, lmc_pci_tbl); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev); +static netdev_tx_t lmc_start_xmit(struct sk_buff *skb, + struct net_device *dev); static int lmc_rx (struct net_device *dev); static int lmc_open(struct net_device *dev); static int lmc_close(struct net_device *dev); @@ -114,27 +108,20 @@ static void lmc_driver_timeout(struct net_device *dev); * linux reserves 16 device specific IOCTLs. We call them * LMCIOC* to control various bits of our world. */ -int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ +int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); lmc_ctl_t ctl; - int ret; - u_int16_t regVal; + int ret = -EOPNOTSUPP; + u16 regVal; unsigned long flags; - struct sppp *sp; - - ret = -EOPNOTSUPP; - - sc = dev->priv; - lmc_trace(dev, "lmc_ioctl in"); /* * Most functions mess with the structure * Disable interrupts while we do the polling */ - spin_lock_irqsave(&sc->lmc_lock, flags); switch (cmd) { /* @@ -149,7 +136,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; case LMCIOCSINFO: /*fold01*/ - sp = &((struct ppp_device *) dev)->sppp; if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; @@ -165,6 +151,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_status (sc, &ctl); if(ctl.crc_length != sc->ictl.crc_length) { @@ -174,26 +161,22 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ else sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE; } - - if (ctl.keepalive_onoff == LMC_CTL_OFF) - sp->pp_flags &= ~PP_KEEPALIVE; /* Turn off */ - else - sp->pp_flags |= PP_KEEPALIVE; /* Turn on */ + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; case LMCIOCIFTYPE: /*fold01*/ { - u_int16_t old_type = sc->if_type; - u_int16_t new_type; + u16 old_type = sc->if_type; + u16 new_type; if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } - if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) { + if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u16))) { ret = -EFAULT; break; } @@ -205,19 +188,18 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; /* no change */ } + spin_lock_irqsave(&sc->lmc_lock, flags); lmc_proto_close(sc); - lmc_proto_detach(sc); sc->if_type = new_type; -// lmc_proto_init(sc); lmc_proto_attach(sc); - lmc_proto_open(sc); - - ret = 0 ; - break ; + ret = lmc_proto_open(sc); + spin_unlock_irqrestore(&sc->lmc_lock, flags); + break; } case LMCIOCGETXINFO: /*fold01*/ + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic0 = 0xBEEFCAFE; sc->lmc_xinfo.PciCardType = sc->lmc_cardtype; @@ -230,6 +212,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ; sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc); sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16); + spin_unlock_irqrestore(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic1 = 0xDEADBEEF; @@ -241,51 +224,57 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; - case LMCIOCGETLMCSTATS: /*fold01*/ - if (sc->lmc_cardtype == LMC_CARDTYPE_T1){ - lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB); - sc->stats.framingBitErrorCount += - lmc_mii_readreg (sc, 0, 18) & 0xff; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_MSB); - sc->stats.framingBitErrorCount += - (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_LSB); - sc->stats.lineCodeViolationCount += - lmc_mii_readreg (sc, 0, 18) & 0xff; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_MSB); - sc->stats.lineCodeViolationCount += - (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_AERR); - regVal = lmc_mii_readreg (sc, 0, 18) & 0xff; - - sc->stats.lossOfFrameCount += - (regVal & T1FRAMER_LOF_MASK) >> 4; - sc->stats.changeOfFrameAlignmentCount += - (regVal & T1FRAMER_COFA_MASK) >> 2; - sc->stats.severelyErroredFrameCount += - regVal & T1FRAMER_SEF_MASK; - } - - if (copy_to_user(ifr->ifr_data, &sc->stats, - sizeof (struct lmc_statistics))) - ret = -EFAULT; - else - ret = 0; - break; + case LMCIOCGETLMCSTATS: + spin_lock_irqsave(&sc->lmc_lock, flags); + if (sc->lmc_cardtype == LMC_CARDTYPE_T1) { + lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_LSB); + sc->extra_stats.framingBitErrorCount += + lmc_mii_readreg(sc, 0, 18) & 0xff; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_MSB); + sc->extra_stats.framingBitErrorCount += + (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_LSB); + sc->extra_stats.lineCodeViolationCount += + lmc_mii_readreg(sc, 0, 18) & 0xff; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_MSB); + sc->extra_stats.lineCodeViolationCount += + (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_AERR); + regVal = lmc_mii_readreg(sc, 0, 18) & 0xff; + + sc->extra_stats.lossOfFrameCount += + (regVal & T1FRAMER_LOF_MASK) >> 4; + sc->extra_stats.changeOfFrameAlignmentCount += + (regVal & T1FRAMER_COFA_MASK) >> 2; + sc->extra_stats.severelyErroredFrameCount += + regVal & T1FRAMER_SEF_MASK; + } + spin_unlock_irqrestore(&sc->lmc_lock, flags); + if (copy_to_user(ifr->ifr_data, &sc->lmc_device->stats, + sizeof(sc->lmc_device->stats)) || + copy_to_user(ifr->ifr_data + sizeof(sc->lmc_device->stats), + &sc->extra_stats, sizeof(sc->extra_stats))) + ret = -EFAULT; + else + ret = 0; + break; - case LMCIOCCLEARLMCSTATS: /*fold01*/ - if (!capable(CAP_NET_ADMIN)){ - ret = -EPERM; - break; - } + case LMCIOCCLEARLMCSTATS: + if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + break; + } - memset (&sc->stats, 0, sizeof (struct lmc_statistics)); - sc->stats.check = STATCHECK; - sc->stats.version_size = (DRIVER_VERSION << 16) + - sizeof (struct lmc_statistics); - sc->stats.lmc_cardtype = sc->lmc_cardtype; - ret = 0; - break; + spin_lock_irqsave(&sc->lmc_lock, flags); + memset(&sc->lmc_device->stats, 0, sizeof(sc->lmc_device->stats)); + memset(&sc->extra_stats, 0, sizeof(sc->extra_stats)); + sc->extra_stats.check = STATCHECK; + sc->extra_stats.version_size = (DRIVER_VERSION << 16) + + sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats); + sc->extra_stats.lmc_cardtype = sc->lmc_cardtype; + spin_unlock_irqrestore(&sc->lmc_lock, flags); + ret = 0; + break; case LMCIOCSETCIRCUIT: /*fold01*/ if (!capable(CAP_NET_ADMIN)){ @@ -302,8 +291,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ ret = -EFAULT; break; } + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_circuit_type(sc, ctl.circuit_type); sc->ictl.circuit_type = ctl.circuit_type; + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; @@ -314,12 +305,14 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } + spin_lock_irqsave(&sc->lmc_lock, flags); /* Reset driver and bring back to current state */ printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); lmc_running_reset (dev); printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16)); + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; @@ -330,7 +323,8 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ ret = -EFAULT; break; } - if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf))) + if (copy_to_user(ifr->ifr_data + sizeof(u32), lmcEventLogBuf, + sizeof(lmcEventLogBuf))) ret = -EFAULT; else ret = 0; @@ -357,14 +351,15 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ netif_stop_queue(dev); - if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { + if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { ret = -EFAULT; break; - } + } switch(xc.command){ case lmc_xilinx_reset: /*fold02*/ { u16 mii; + spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); /* @@ -423,6 +418,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ lmc_led_off(sc, LMC_DS3_LED2); } } + spin_unlock_irqrestore(&sc->lmc_lock, flags); @@ -435,6 +431,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ { u16 mii; int timeout = 500000; + spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); /* @@ -470,13 +467,14 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) - ; + cpu_relax(); /* * stop driving Xilinx-related signals */ lmc_gpio_mkinput(sc, 0xff); + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0x0; @@ -498,7 +496,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ data = kmalloc(xc.len, GFP_KERNEL); if (!data) { - printk(KERN_WARNING "%s: Failed to allocate memory for copy\n", dev->name); ret = -ENOMEM; break; } @@ -512,6 +509,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data); + spin_lock_irqsave(&sc->lmc_lock, flags); lmc_gpio_mkinput(sc, 0xff); /* @@ -564,7 +562,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) - ; + cpu_relax(); printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout); @@ -607,6 +605,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); + spin_unlock_irqrestore(&sc->lmc_lock, flags); kfree(data); @@ -630,8 +629,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/ - lmc_trace(dev, "lmc_ioctl out"); return ret; @@ -641,14 +638,12 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ /* the watchdog process that cruises around */ static void lmc_watchdog (unsigned long data) /*fold00*/ { - struct net_device *dev = (struct net_device *) data; - lmc_softc_t *sc; + struct net_device *dev = (struct net_device *)data; + lmc_softc_t *sc = dev_to_sc(dev); int link_status; - u_int32_t ticks; + u32 ticks; unsigned long flags; - sc = dev->priv; - lmc_trace(dev, "lmc_watchdog in"); spin_lock_irqsave(&sc->lmc_lock, flags); @@ -677,22 +672,22 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ * check for a transmit interrupt timeout * Has the packet xmt vs xmt serviced threshold been exceeded */ if (sc->lmc_taint_tx == sc->lastlmc_taint_tx && - sc->stats.tx_packets > sc->lasttx_packets && - sc->tx_TimeoutInd == 0) + sc->lmc_device->stats.tx_packets > sc->lasttx_packets && + sc->tx_TimeoutInd == 0) { /* wait for the watchdog to come around again */ sc->tx_TimeoutInd = 1; } else if (sc->lmc_taint_tx == sc->lastlmc_taint_tx && - sc->stats.tx_packets > sc->lasttx_packets && - sc->tx_TimeoutInd) + sc->lmc_device->stats.tx_packets > sc->lasttx_packets && + sc->tx_TimeoutInd) { LMC_EVENT_LOG(LMC_EVENT_XMTINTTMO, LMC_CSR_READ (sc, csr_status), 0); sc->tx_TimeoutDisplay = 1; - sc->stats.tx_TimeoutCnt++; + sc->extra_stats.tx_TimeoutCnt++; /* DEC chip is stuck, hit it with a RESET!!!! */ lmc_running_reset (dev); @@ -712,13 +707,11 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ /* reset the transmit timeout detection flag */ sc->tx_TimeoutInd = 0; sc->lastlmc_taint_tx = sc->lmc_taint_tx; - sc->lasttx_packets = sc->stats.tx_packets; - } - else - { + sc->lasttx_packets = sc->lmc_device->stats.tx_packets; + } else { sc->tx_TimeoutInd = 0; sc->lastlmc_taint_tx = sc->lmc_taint_tx; - sc->lasttx_packets = sc->stats.tx_packets; + sc->lasttx_packets = sc->lmc_device->stats.tx_packets; } /* --- end time out check ----------------------------------- */ @@ -748,19 +741,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ sc->last_link_status = 1; /* lmc_reset (sc); Again why reset??? */ - /* Inform the world that link protocol is back up. */ netif_carrier_on(dev); - - /* Now we have to tell the syncppp that we had an outage - * and that it should deal. Calling sppp_reopen here - * should do the trick, but we may have to call sppp_close - * when the link goes down, and call sppp_open here. - * Subject to more testing. - * --bbraun - */ - - lmc_proto_reopen(sc); - } /* Call media specific watchdog functions */ @@ -816,113 +797,98 @@ kick_timer: } -static void lmc_setup(struct net_device * const dev) /*fold00*/ +static int lmc_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - lmc_trace(dev, "lmc_setup in"); - - dev->type = ARPHRD_HDLC; - dev->hard_start_xmit = lmc_start_xmit; - dev->open = lmc_open; - dev->stop = lmc_close; - dev->get_stats = lmc_get_stats; - dev->do_ioctl = lmc_ioctl; - dev->tx_timeout = lmc_driver_timeout; - dev->watchdog_timeo = (HZ); /* 1 second */ - - lmc_trace(dev, "lmc_setup out"); + if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT) + return 0; + return -EINVAL; } +static const struct net_device_ops lmc_ops = { + .ndo_open = lmc_open, + .ndo_stop = lmc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = lmc_ioctl, + .ndo_tx_timeout = lmc_driver_timeout, + .ndo_get_stats = lmc_get_stats, +}; -static int __devinit lmc_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct net_device *dev; - lmc_softc_t *sc; - u16 subdevice; - u_int16_t AdapModelNum; - int err = -ENOMEM; - static int cards_found; -#ifndef GCOM - /* We name by type not by vendor */ - static const char lmcname[] = "hdlc%d"; -#else - /* - * GCOM uses LMC vendor name so that clients can know which card - * to attach to. - */ - static const char lmcname[] = "lmc%d"; -#endif - - - /* - * Allocate our own device structure - */ - dev = alloc_netdev(sizeof(lmc_softc_t), lmcname, lmc_setup); - if (!dev) { - printk (KERN_ERR "lmc:alloc_netdev for device failed\n"); - goto out1; - } - - lmc_trace(dev, "lmc_init_one in"); - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "lmc: pci enable failed:%d\n", err); - goto out2; - } - - if (pci_request_regions(pdev, "lmc")) { - printk(KERN_ERR "lmc: pci_request_region failed\n"); - err = -EIO; - goto out3; - } - - pci_set_drvdata(pdev, dev); - - if(lmc_first_load == 0){ - printk(KERN_INFO "Lan Media Corporation WAN Driver Version %d.%d.%d\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION,DRIVER_SUB_VERSION); - lmc_first_load = 1; - } - - sc = dev->priv; - sc->lmc_device = dev; - sc->name = dev->name; - - /* Initialize the sppp layer */ - /* An ioctl can cause a subsequent detach for raw frame interface */ - sc->if_type = LMC_PPP; - sc->check = 0xBEAFCAFE; - dev->base_addr = pci_resource_start(pdev, 0); - dev->irq = pdev->irq; - - SET_NETDEV_DEV(dev, &pdev->dev); - - /* - * This will get the protocol layer ready and do any 1 time init's - * Must have a valid sc and dev structure - */ - lmc_proto_init(sc); - - lmc_proto_attach(sc); + lmc_softc_t *sc; + struct net_device *dev; + u16 subdevice; + u16 AdapModelNum; + int err; + static int cards_found; + + /* lmc_trace(dev, "lmc_init_one in"); */ + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "lmc: pci enable failed: %d\n", err); + return err; + } - /* - * Why were we changing this??? - dev->tx_queue_len = 100; - */ + err = pci_request_regions(pdev, "lmc"); + if (err) { + printk(KERN_ERR "lmc: pci_request_region failed\n"); + goto err_req_io; + } - /* Init the spin lock so can call it latter */ + /* + * Allocate our own device structure + */ + sc = kzalloc(sizeof(lmc_softc_t), GFP_KERNEL); + if (!sc) { + err = -ENOMEM; + goto err_kzalloc; + } - spin_lock_init(&sc->lmc_lock); - pci_set_master(pdev); + dev = alloc_hdlcdev(sc); + if (!dev) { + printk(KERN_ERR "lmc:alloc_netdev for device failed\n"); + goto err_hdlcdev; + } - printk ("%s: detected at %lx, irq %d\n", dev->name, - dev->base_addr, dev->irq); - if (register_netdev (dev) != 0) { - printk (KERN_ERR "%s: register_netdev failed.\n", dev->name); - goto out4; - } + dev->type = ARPHRD_HDLC; + dev_to_hdlc(dev)->xmit = lmc_start_xmit; + dev_to_hdlc(dev)->attach = lmc_attach; + dev->netdev_ops = &lmc_ops; + dev->watchdog_timeo = HZ; /* 1 second */ + dev->tx_queue_len = 100; + sc->lmc_device = dev; + sc->name = dev->name; + sc->if_type = LMC_PPP; + sc->check = 0xBEAFCAFE; + dev->base_addr = pci_resource_start(pdev, 0); + dev->irq = pdev->irq; + pci_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + /* + * This will get the protocol layer ready and do any 1 time init's + * Must have a valid sc and dev structure + */ + lmc_proto_attach(sc); + + /* Init the spin lock so can call it latter */ + + spin_lock_init(&sc->lmc_lock); + pci_set_master(pdev); + + printk(KERN_INFO "%s: detected at %lx, irq %d\n", dev->name, + dev->base_addr, dev->irq); + + err = register_hdlc_device(dev); + if (err) { + printk(KERN_ERR "%s: register_netdev failed.\n", dev->name); + free_netdev(dev); + goto err_hdlcdev; + } sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN; sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; @@ -938,27 +904,27 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, switch (subdevice) { case PCI_DEVICE_ID_LMC_HSSI: - printk ("%s: LMC HSSI\n", dev->name); + printk(KERN_INFO "%s: LMC HSSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_HSSI; sc->lmc_media = &lmc_hssi_media; break; case PCI_DEVICE_ID_LMC_DS3: - printk ("%s: LMC DS3\n", dev->name); + printk(KERN_INFO "%s: LMC DS3\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_DS3; sc->lmc_media = &lmc_ds3_media; break; case PCI_DEVICE_ID_LMC_SSI: - printk ("%s: LMC SSI\n", dev->name); + printk(KERN_INFO "%s: LMC SSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_SSI; sc->lmc_media = &lmc_ssi_media; break; case PCI_DEVICE_ID_LMC_T1: - printk ("%s: LMC T1\n", dev->name); + printk(KERN_INFO "%s: LMC T1\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_T1; sc->lmc_media = &lmc_t1_media; break; default: - printk (KERN_WARNING "%s: LMC UNKOWN CARD!\n", dev->name); + printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name); break; } @@ -976,32 +942,28 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, */ AdapModelNum = (lmc_mii_readreg (sc, 0, 3) & 0x3f0) >> 4; - if ((AdapModelNum == LMC_ADAP_T1 - && subdevice == PCI_DEVICE_ID_LMC_T1) || /* detect LMC1200 */ - (AdapModelNum == LMC_ADAP_SSI - && subdevice == PCI_DEVICE_ID_LMC_SSI) || /* detect LMC1000 */ - (AdapModelNum == LMC_ADAP_DS3 - && subdevice == PCI_DEVICE_ID_LMC_DS3) || /* detect LMC5245 */ - (AdapModelNum == LMC_ADAP_HSSI - && subdevice == PCI_DEVICE_ID_LMC_HSSI)) - { /* detect LMC5200 */ + if ((AdapModelNum != LMC_ADAP_T1 || /* detect LMC1200 */ + subdevice != PCI_DEVICE_ID_LMC_T1) && + (AdapModelNum != LMC_ADAP_SSI || /* detect LMC1000 */ + subdevice != PCI_DEVICE_ID_LMC_SSI) && + (AdapModelNum != LMC_ADAP_DS3 || /* detect LMC5245 */ + subdevice != PCI_DEVICE_ID_LMC_DS3) && + (AdapModelNum != LMC_ADAP_HSSI || /* detect LMC5200 */ + subdevice != PCI_DEVICE_ID_LMC_HSSI)) + printk(KERN_WARNING "%s: Model number (%d) miscompare for PCI" + " Subsystem ID = 0x%04x\n", + dev->name, AdapModelNum, subdevice); - } - else { - printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n", - dev->name, AdapModelNum, subdevice); -// return (NULL); - } /* * reset clock */ LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL); sc->board_idx = cards_found++; - sc->stats.check = STATCHECK; - sc->stats.version_size = (DRIVER_VERSION << 16) + - sizeof (struct lmc_statistics); - sc->stats.lmc_cardtype = sc->lmc_cardtype; + sc->extra_stats.check = STATCHECK; + sc->extra_stats.version_size = (DRIVER_VERSION << 16) + + sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats); + sc->extra_stats.lmc_cardtype = sc->lmc_cardtype; sc->lmc_ok = 0; sc->last_link_status = 0; @@ -1009,68 +971,59 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, lmc_trace(dev, "lmc_init_one out"); return 0; - out4: - lmc_proto_detach(sc); - out3: - if (pdev) { - pci_release_regions(pdev); - pci_set_drvdata(pdev, NULL); - } - out2: - free_netdev(dev); - out1: - return err; +err_hdlcdev: + kfree(sc); +err_kzalloc: + pci_release_regions(pdev); +err_req_io: + pci_disable_device(pdev); + return err; } /* * Called from pci when removing module. */ -static void __devexit lmc_remove_one (struct pci_dev *pdev) +static void lmc_remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - lmc_softc_t *sc = dev->priv; - - printk("%s: removing...\n", dev->name); - lmc_proto_detach(sc); - unregister_netdev(dev); - free_netdev(dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } + struct net_device *dev = pci_get_drvdata(pdev); + + if (dev) { + printk(KERN_DEBUG "%s: removing...\n", dev->name); + unregister_hdlc_device(dev); + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); + } } /* After this is called, packets can be sent. * Does not initialize the addresses */ -static int lmc_open (struct net_device *dev) /*fold00*/ +static int lmc_open(struct net_device *dev) { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); + int err; lmc_trace(dev, "lmc_open in"); lmc_led_on(sc, LMC_DS3_LED0); - lmc_dec_reset (sc); - lmc_reset (sc); - - LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0); - LMC_EVENT_LOG(LMC_EVENT_RESET2, - lmc_mii_readreg (sc, 0, 16), - lmc_mii_readreg (sc, 0, 17)); + lmc_dec_reset(sc); + lmc_reset(sc); + LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ(sc, csr_status), 0); + LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg(sc, 0, 16), + lmc_mii_readreg(sc, 0, 17)); if (sc->lmc_ok){ lmc_trace(dev, "lmc_open lmc_ok out"); - return (0); + return 0; } lmc_softreset (sc); /* Since we have to use PCI bus, this should work on x86,alpha,ppc */ - if (request_irq (dev->irq, &lmc_interrupt, IRQF_SHARED, dev->name, dev)){ + if (request_irq (dev->irq, lmc_interrupt, IRQF_SHARED, dev->name, dev)){ printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq); lmc_trace(dev, "lmc_open irq failed out"); return -EAGAIN; @@ -1105,14 +1058,11 @@ static int lmc_open (struct net_device *dev) /*fold00*/ /* dev->flags |= IFF_UP; */ - lmc_proto_open(sc); - - dev->do_ioctl = lmc_ioctl; - + if ((err = lmc_proto_open(sc)) != 0) + return err; netif_start_queue(dev); - - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; /* * select what interrupts we want to get @@ -1150,12 +1100,12 @@ static int lmc_open (struct net_device *dev) /*fold00*/ init_timer (&sc->timer); sc->timer.expires = jiffies + HZ; sc->timer.data = (unsigned long) dev; - sc->timer.function = &lmc_watchdog; + sc->timer.function = lmc_watchdog; add_timer (&sc->timer); lmc_trace(dev, "lmc_open out"); - return (0); + return 0; } /* Total reset to compensate for the AdTran DSU doing bad things @@ -1164,10 +1114,9 @@ static int lmc_open (struct net_device *dev) /*fold00*/ static void lmc_running_reset (struct net_device *dev) /*fold00*/ { + lmc_softc_t *sc = dev_to_sc(dev); - lmc_softc_t *sc = (lmc_softc_t *) dev->priv; - - lmc_trace(dev, "lmc_runnig_reset in"); + lmc_trace(dev, "lmc_running_reset in"); /* stop interrupts */ /* Clear the interrupt mask */ @@ -1183,7 +1132,7 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/ netif_wake_queue(dev); sc->lmc_txfull = 0; - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK; LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask); @@ -1199,14 +1148,13 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/ * This disables the timer for the watchdog and keepalives, * and disables the irq for dev. */ -static int lmc_close (struct net_device *dev) /*fold00*/ +static int lmc_close(struct net_device *dev) { /* not calling release_region() as we should */ - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); lmc_trace(dev, "lmc_close in"); - - sc = dev->priv; + sc->lmc_ok = 0; sc->lmc_media->set_link_status (sc, 0); del_timer (&sc->timer); @@ -1214,7 +1162,7 @@ static int lmc_close (struct net_device *dev) /*fold00*/ lmc_ifdown (dev); lmc_trace(dev, "lmc_close out"); - + return 0; } @@ -1222,16 +1170,16 @@ static int lmc_close (struct net_device *dev) /*fold00*/ /* When the interface goes down, this is called */ static int lmc_ifdown (struct net_device *dev) /*fold00*/ { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); u32 csr6; int i; lmc_trace(dev, "lmc_ifdown in"); - + /* Don't let anything else go on right now */ // dev->start = 0; netif_stop_queue(dev); - sc->stats.tx_tbusy1++ ; + sc->extra_stats.tx_tbusy1++; /* stop interrupts */ /* Clear the interrupt mask */ @@ -1243,8 +1191,8 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */ LMC_CSR_WRITE (sc, csr_command, csr6); - sc->stats.rx_missed_errors += - LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; + sc->lmc_device->stats.rx_missed_errors += + LMC_CSR_READ(sc, csr_missed_frames) & 0xffff; /* release the interrupt */ if(sc->got_irq == 1){ @@ -1275,7 +1223,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ lmc_led_off (sc, LMC_MII16_LED_ALL); netif_wake_queue(dev); - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; lmc_trace(dev, "lmc_ifdown out"); @@ -1288,7 +1236,7 @@ static int lmc_ifdown (struct net_device *dev) /*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; + lmc_softc_t *sc = dev_to_sc(dev); u32 csr; int i; s32 stat; @@ -1299,8 +1247,6 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ lmc_trace(dev, "lmc_interrupt in"); - sc = dev->priv; - spin_lock(&sc->lmc_lock); /* @@ -1353,7 +1299,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ int n_compl = 0 ; /* reset the transmit timeout detection flag -baz */ - sc->stats.tx_NoCompleteCnt = 0; + sc->extra_stats.tx_NoCompleteCnt = 0; badtx = sc->lmc_taint_tx; i = badtx % LMC_TXDESCS; @@ -1377,27 +1323,25 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ if (sc->lmc_txq[i] == NULL) continue; - /* - * Check the total error summary to look for any errors - */ - if (stat & 0x8000) { - sc->stats.tx_errors++; - if (stat & 0x4104) - sc->stats.tx_aborted_errors++; - if (stat & 0x0C00) - sc->stats.tx_carrier_errors++; - if (stat & 0x0200) - sc->stats.tx_window_errors++; - if (stat & 0x0002) - sc->stats.tx_fifo_errors++; + /* + * Check the total error summary to look for any errors + */ + if (stat & 0x8000) { + sc->lmc_device->stats.tx_errors++; + if (stat & 0x4104) + sc->lmc_device->stats.tx_aborted_errors++; + if (stat & 0x0C00) + sc->lmc_device->stats.tx_carrier_errors++; + if (stat & 0x0200) + sc->lmc_device->stats.tx_window_errors++; + if (stat & 0x0002) + sc->lmc_device->stats.tx_fifo_errors++; + } else { + sc->lmc_device->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff; + + sc->lmc_device->stats.tx_packets++; } - else { - - sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff; - - sc->stats.tx_packets++; - } - + // dev_kfree_skb(sc->lmc_txq[i]); dev_kfree_skb_irq(sc->lmc_txq[i]); sc->lmc_txq[i] = NULL; @@ -1414,13 +1358,13 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ LMC_EVENT_LOG(LMC_EVENT_TBUSY0, n_compl, 0); sc->lmc_txfull = 0; netif_wake_queue(dev); - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; #ifdef DEBUG - sc->stats.dirtyTx = badtx; - sc->stats.lmc_next_tx = sc->lmc_next_tx; - sc->stats.lmc_txfull = sc->lmc_txfull; + sc->extra_stats.dirtyTx = badtx; + sc->extra_stats.lmc_next_tx = sc->lmc_next_tx; + sc->extra_stats.lmc_txfull = sc->lmc_txfull; #endif sc->lmc_taint_tx = badtx; @@ -1475,18 +1419,16 @@ lmc_int_fail_out: return IRQ_RETVAL(handled); } -static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/ +static netdev_tx_t lmc_start_xmit(struct sk_buff *skb, + struct net_device *dev) { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); u32 flag; int entry; - int ret = 0; unsigned long flags; lmc_trace(dev, "lmc_start_xmit in"); - sc = dev->priv; - spin_lock_irqsave(&sc->lmc_lock, flags); /* normal path, tbusy known to be zero */ @@ -1531,8 +1473,8 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1) { /* ring full, go busy */ sc->lmc_txfull = 1; - netif_stop_queue(dev); - sc->stats.tx_tbusy1++ ; + netif_stop_queue(dev); + sc->extra_stats.tx_tbusy1++; LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0); } #endif @@ -1549,7 +1491,7 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 * the watchdog timer handler. -baz */ - sc->stats.tx_NoCompleteCnt++; + sc->extra_stats.tx_NoCompleteCnt++; sc->lmc_next_tx++; /* give ownership to the chip */ @@ -1559,18 +1501,16 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 /* send now! */ LMC_CSR_WRITE (sc, csr_txpoll, 0); - dev->trans_start = jiffies; - spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_start_xmit_out"); - return ret; + return NETDEV_TX_OK; } -static int lmc_rx (struct net_device *dev) /*fold00*/ +static int lmc_rx(struct net_device *dev) { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); int i; int rx_work_limit = LMC_RXDESCS; unsigned int next_rx; @@ -1582,8 +1522,6 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ lmc_trace(dev, "lmc_rx in"); - sc = dev->priv; - lmc_led_on(sc, LMC_DS3_LED3); rxIntLoopCnt = 0; /* debug -baz */ @@ -1596,39 +1534,38 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ rxIntLoopCnt++; /* debug -baz */ len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER); if ((stat & 0x0300) != 0x0300) { /* Check first segment and last segment */ - if ((stat & 0x0000ffff) != 0x7fff) { - /* Oversized frame */ - sc->stats.rx_length_errors++; - goto skip_packet; - } - } - - if(stat & 0x00000008){ /* Catch a dribbling bit error */ - sc->stats.rx_errors++; - sc->stats.rx_frame_errors++; - goto skip_packet; - } + if ((stat & 0x0000ffff) != 0x7fff) { + /* Oversized frame */ + sc->lmc_device->stats.rx_length_errors++; + goto skip_packet; + } + } + if (stat & 0x00000008) { /* Catch a dribbling bit error */ + sc->lmc_device->stats.rx_errors++; + sc->lmc_device->stats.rx_frame_errors++; + goto skip_packet; + } - if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */ - sc->stats.rx_errors++; - sc->stats.rx_crc_errors++; - goto skip_packet; - } + if (stat & 0x00000004) { /* Catch a CRC error by the Xilinx */ + sc->lmc_device->stats.rx_errors++; + sc->lmc_device->stats.rx_crc_errors++; + goto skip_packet; + } - if (len > LMC_PKT_BUF_SZ){ - sc->stats.rx_length_errors++; - localLengthErrCnt++; - goto skip_packet; - } + if (len > LMC_PKT_BUF_SZ) { + sc->lmc_device->stats.rx_length_errors++; + localLengthErrCnt++; + goto skip_packet; + } - if (len < sc->lmc_crcSize + 2) { - sc->stats.rx_length_errors++; - sc->stats.rx_SmallPktCnt++; - localLengthErrCnt++; - goto skip_packet; - } + if (len < sc->lmc_crcSize + 2) { + sc->lmc_device->stats.rx_length_errors++; + sc->extra_stats.rx_SmallPktCnt++; + localLengthErrCnt++; + goto skip_packet; + } if(stat & 0x00004000){ printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name); @@ -1654,9 +1591,8 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ goto skip_packet; } - dev->last_rx = jiffies; - sc->stats.rx_packets++; - sc->stats.rx_bytes += len; + sc->lmc_device->stats.rx_packets++; + sc->lmc_device->stats.rx_bytes += len; LMC_CONSOLE_LOG("recv", skb->data, len); @@ -1678,7 +1614,6 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ skb_put (skb, len); skb->protocol = lmc_proto_type(sc, skb); - skb->protocol = htons(ETH_P_WAN_PPP); skb_reset_mac_header(skb); /* skb_reset_network_header(skb); */ skb->dev = dev; @@ -1703,7 +1638,7 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ * in which care we'll try to allocate the buffer * again. (once a second) */ - sc->stats.rx_BuffAllocErr++; + sc->extra_stats.rx_BuffAllocErr++; LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len); sc->failed_recv_alloc = 1; goto skip_out_of_mem; @@ -1716,7 +1651,7 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ } skb_copy_from_linear_data(skb, skb_put(nsb, len), len); - nsb->protocol = lmc_proto_type(sc, skb); + nsb->protocol = lmc_proto_type(sc, nsb); skb_reset_mac_header(nsb); /* skb_reset_network_header(nsb); */ nsb->dev = dev; @@ -1738,16 +1673,14 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ * descriptors with bogus packets * if (localLengthErrCnt > LMC_RXDESCS - 3) { - sc->stats.rx_BadPktSurgeCnt++; - LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE, - localLengthErrCnt, - sc->stats.rx_BadPktSurgeCnt); + sc->extra_stats.rx_BadPktSurgeCnt++; + LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE, localLengthErrCnt, + sc->extra_stats.rx_BadPktSurgeCnt); } */ /* save max count of receive descriptors serviced */ - if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) { - sc->stats.rxIntLoopCnt = rxIntLoopCnt; /* debug -baz */ - } + if (rxIntLoopCnt > sc->extra_stats.rxIntLoopCnt) + sc->extra_stats.rxIntLoopCnt = rxIntLoopCnt; /* debug -baz */ #ifdef DEBUG if (rxIntLoopCnt == 0) @@ -1774,44 +1707,32 @@ skip_out_of_mem: return 0; } -static struct net_device_stats *lmc_get_stats (struct net_device *dev) /*fold00*/ +static struct net_device_stats *lmc_get_stats(struct net_device *dev) { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); unsigned long flags; lmc_trace(dev, "lmc_get_stats in"); - spin_lock_irqsave(&sc->lmc_lock, flags); - sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; + sc->lmc_device->stats.rx_missed_errors += LMC_CSR_READ(sc, csr_missed_frames) & 0xffff; spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_get_stats out"); - return (struct net_device_stats *) &sc->stats; + return &sc->lmc_device->stats; } static struct pci_driver lmc_driver = { .name = "lmc", .id_table = lmc_pci_tbl, .probe = lmc_init_one, - .remove = __devexit_p(lmc_remove_one), + .remove = lmc_remove_one, }; -static int __init init_lmc(void) -{ - return pci_register_driver(&lmc_driver); -} - -static void __exit exit_lmc(void) -{ - pci_unregister_driver(&lmc_driver); -} - -module_init(init_lmc); -module_exit(exit_lmc); +module_pci_driver(lmc_driver); unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/ { @@ -1959,17 +1880,18 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/ /* * Sets end of ring */ - sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */ - sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */ + if (i != 0) { + sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */ + sc->lmc_rxring[i - 1].buffer2 = virt_to_bus(&sc->lmc_rxring[0]); /* Point back to the start */ + } LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */ - /* Initialize the transmit rings and buffers */ for (i = 0; i < LMC_TXDESCS; i++) { if (sc->lmc_txq[i] != NULL){ /* have buffer */ dev_kfree_skb(sc->lmc_txq[i]); /* free it */ - sc->stats.tx_dropped++; /* We just dropped a packet */ + sc->lmc_device->stats.tx_dropped++; /* We just dropped a packet */ } sc->lmc_txq[i] = NULL; sc->lmc_txring[i].status = 0x00000000; @@ -1981,7 +1903,7 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_softreset out"); } -void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ +void lmc_gpio_mkinput(lmc_softc_t * const sc, u32 bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in"); sc->lmc_gpio_io &= ~bits; @@ -1989,7 +1911,7 @@ void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out"); } -void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ +void lmc_gpio_mkoutput(lmc_softc_t * const sc, u32 bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in"); sc->lmc_gpio_io |= bits; @@ -1997,7 +1919,7 @@ void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out"); } -void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ +void lmc_led_on(lmc_softc_t * const sc, u32 led) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_led_on in"); if((~sc->lmc_miireg16) & led){ /* Already on! */ @@ -2010,7 +1932,7 @@ void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_led_on out"); } -void lmc_led_off(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ +void lmc_led_off(lmc_softc_t * const sc, u32 led) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_led_off in"); if(sc->lmc_miireg16 & led){ /* Already set don't do anything */ @@ -2060,13 +1982,13 @@ static void lmc_reset(lmc_softc_t * const sc) /*fold00*/ */ sc->lmc_media->init(sc); - sc->stats.resetCount++; + sc->extra_stats.resetCount++; lmc_trace(sc->lmc_device, "lmc_reset out"); } static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/ { - u_int32_t val; + u32 val; lmc_trace(sc->lmc_device, "lmc_dec_reset in"); /* @@ -2150,23 +2072,21 @@ static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00 lmc_trace(sc->lmc_device, "lmc_initcsrs out"); } -static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ - lmc_softc_t *sc; +static void lmc_driver_timeout(struct net_device *dev) +{ + lmc_softc_t *sc = dev_to_sc(dev); u32 csr6; unsigned long flags; lmc_trace(dev, "lmc_driver_timeout in"); - sc = dev->priv; - spin_lock_irqsave(&sc->lmc_lock, flags); printk("%s: Xmitter busy|\n", dev->name); - sc->stats.tx_tbusy_calls++ ; - if (jiffies - dev->trans_start < TX_TIMEOUT) { - goto bug_out; - } + sc->extra_stats.tx_tbusy_calls++; + if (jiffies - dev_trans_start(dev) < TX_TIMEOUT) + goto bug_out; /* * Chip seems to have locked up @@ -2177,7 +2097,7 @@ static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO, LMC_CSR_READ (sc, csr_status), - sc->stats.tx_ProcTimeout); + sc->extra_stats.tx_ProcTimeout); lmc_running_reset (dev); @@ -2194,16 +2114,16 @@ static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ /* immediate transmit */ LMC_CSR_WRITE (sc, csr_txpoll, 0); - sc->stats.tx_errors++; - sc->stats.tx_ProcTimeout++; /* -baz */ + sc->lmc_device->stats.tx_errors++; + sc->extra_stats.tx_ProcTimeout++; /* -baz */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ bug_out: spin_unlock_irqrestore(&sc->lmc_lock, flags); - lmc_trace(dev, "lmc_driver_timout out"); + lmc_trace(dev, "lmc_driver_timeout out"); } diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index 8aa461c941c..5920c996fcd 100644 --- a/drivers/net/wan/lmc/lmc_media.c +++ b/drivers/net/wan/lmc/lmc_media.c @@ -6,7 +6,6 @@ #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> -#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/in.h> #include <linux/if_arp.h> @@ -16,8 +15,6 @@ #include <linux/inet.h> #include <linux/bitops.h> -#include <net/syncppp.h> - #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> #include <asm/dma.h> @@ -95,8 +92,7 @@ static void lmc_dummy_set_1 (lmc_softc_t * const, int); static void lmc_dummy_set2_1 (lmc_softc_t * const, lmc_ctl_t *); static inline void write_av9110_bit (lmc_softc_t *, int); -static void write_av9110 (lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t, - u_int32_t, u_int32_t); +static void write_av9110(lmc_softc_t *, u32, u32, u32, u32, u32); lmc_media_t lmc_ds3_media = { lmc_ds3_init, /* special media init stuff */ @@ -427,7 +423,7 @@ lmc_ds3_set_scram (lmc_softc_t * const sc, int ie) static int lmc_ds3_get_link_status (lmc_softc_t * const sc) { - u_int16_t link_status, link_status_11; + u16 link_status, link_status_11; int ret = 1; lmc_mii_writereg (sc, 0, 17, 7); @@ -449,7 +445,7 @@ lmc_ds3_get_link_status (lmc_softc_t * const sc) (link_status & LMC_FRAMER_REG0_OOFS)){ ret = 0; if(sc->last_led_err[3] != 1){ - u16 r1; + u16 r1; lmc_mii_writereg (sc, 0, 17, 01); /* Turn on Xbit error as our cisco does */ r1 = lmc_mii_readreg (sc, 0, 18); r1 &= 0xfe; @@ -462,7 +458,7 @@ lmc_ds3_get_link_status (lmc_softc_t * const sc) else { lmc_led_off(sc, LMC_DS3_LED3); /* turn on red LED */ if(sc->last_led_err[3] == 1){ - u16 r1; + u16 r1; lmc_mii_writereg (sc, 0, 17, 01); /* Turn off Xbit error */ r1 = lmc_mii_readreg (sc, 0, 18); r1 |= 0x01; @@ -540,20 +536,19 @@ lmc_ds3_watchdog (lmc_softc_t * const sc) * SSI methods */ -static void -lmc_ssi_init (lmc_softc_t * const sc) +static void lmc_ssi_init(lmc_softc_t * const sc) { - u_int16_t mii17; - int cable; + u16 mii17; + int cable; - sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000; + sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000; - mii17 = lmc_mii_readreg (sc, 0, 17); + mii17 = lmc_mii_readreg(sc, 0, 17); - cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT; - sc->ictl.cable_type = cable; + cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT; + sc->ictl.cable_type = cable; - lmc_gpio_mkoutput (sc, LMC_GEP_SSI_TXCLOCK); + lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); } static void @@ -681,11 +676,11 @@ lmc_ssi_set_speed (lmc_softc_t * const sc, lmc_ctl_t * ctl) static int lmc_ssi_get_link_status (lmc_softc_t * const sc) { - u_int16_t link_status; - u_int32_t ticks; + u16 link_status; + u32 ticks; int ret = 1; int hw_hdsk = 1; - + /* * missing CTS? Hmm. If we require CTS on, we may never get the * link to come up, so omit it in this test. @@ -720,9 +715,9 @@ lmc_ssi_get_link_status (lmc_softc_t * const sc) } else if (ticks == 0 ) { /* no clock found ? */ ret = 0; - if(sc->last_led_err[3] != 1){ - sc->stats.tx_lossOfClockCnt++; - printk(KERN_WARNING "%s: Lost Clock, Link Down\n", sc->name); + if (sc->last_led_err[3] != 1) { + sc->extra_stats.tx_lossOfClockCnt++; + printk(KERN_WARNING "%s: Lost Clock, Link Down\n", sc->name); } sc->last_led_err[3] = 1; lmc_led_on (sc, LMC_MII16_LED3); /* turn ON red LED */ @@ -838,9 +833,7 @@ write_av9110_bit (lmc_softc_t * sc, int c) LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio); } -static void -write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v, - u_int32_t x, u_int32_t r) +static void write_av9110(lmc_softc_t *sc, u32 n, u32 m, u32 v, u32 x, u32 r) { int i; @@ -887,19 +880,13 @@ write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v, | LMC_GEP_SSI_GENERATOR)); } -static void -lmc_ssi_watchdog (lmc_softc_t * const sc) +static void lmc_ssi_watchdog(lmc_softc_t * const sc) { - u_int16_t mii17 = lmc_mii_readreg (sc, 0, 17); - if (((mii17 >> 3) & 7) == 7) - { - lmc_led_off (sc, LMC_MII16_LED2); - } - else - { - lmc_led_on (sc, LMC_MII16_LED2); - } - + u16 mii17 = lmc_mii_readreg(sc, 0, 17); + if (((mii17 >> 3) & 7) == 7) + lmc_led_off(sc, LMC_MII16_LED2); + else + lmc_led_on(sc, LMC_MII16_LED2); } /* @@ -929,7 +916,7 @@ lmc_t1_read (lmc_softc_t * const sc, int a) static void lmc_t1_init (lmc_softc_t * const sc) { - u_int16_t mii16; + u16 mii16; int i; sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1200; @@ -1028,7 +1015,7 @@ lmc_t1_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl) */ static int lmc_t1_get_link_status (lmc_softc_t * const sc) { - u_int16_t link_status; + u16 link_status; int ret = 1; /* LMC5245 (DS3) & LMC1200 (DS1) LED definitions diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index 85315758198..f600075e84a 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c @@ -25,7 +25,6 @@ #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> -#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/in.h> #include <linux/if_arp.h> @@ -36,9 +35,6 @@ #include <linux/workqueue.h> #include <linux/proc_fs.h> #include <linux/bitops.h> - -#include <net/syncppp.h> - #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> #include <asm/dma.h> @@ -50,162 +46,55 @@ #include "lmc_ioctl.h" #include "lmc_proto.h" -/* - * The compile-time variable SPPPSTUP causes the module to be - * compiled without referencing any of the sync ppp routines. - */ -#ifdef SPPPSTUB -#define SPPP_detach(d) (void)0 -#define SPPP_open(d) 0 -#define SPPP_reopen(d) (void)0 -#define SPPP_close(d) (void)0 -#define SPPP_attach(d) (void)0 -#define SPPP_do_ioctl(d,i,c) -EOPNOTSUPP -#else -#define SPPP_attach(x) sppp_attach((x)->pd) -#define SPPP_detach(x) sppp_detach((x)->pd->dev) -#define SPPP_open(x) sppp_open((x)->pd->dev) -#define SPPP_reopen(x) sppp_reopen((x)->pd->dev) -#define SPPP_close(x) sppp_close((x)->pd->dev) -#define SPPP_do_ioctl(x, y, z) sppp_do_ioctl((x)->pd->dev, (y), (z)) -#endif - -// init -void lmc_proto_init(lmc_softc_t *sc) /*FOLD00*/ -{ - lmc_trace(sc->lmc_device, "lmc_proto_init in"); - switch(sc->if_type){ - case LMC_PPP: - sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL); - if (!sc->pd) { - printk("lmc_proto_init(): kmalloc failure!\n"); - return; - } - sc->pd->dev = sc->lmc_device; - sc->if_ptr = sc->pd; - break; - case LMC_RAW: - break; - default: - break; - } - lmc_trace(sc->lmc_device, "lmc_proto_init out"); -} - // attach void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_attach in"); - switch(sc->if_type){ - case LMC_PPP: - { - struct net_device *dev = sc->lmc_device; - SPPP_attach(sc); - dev->do_ioctl = lmc_ioctl; - } - break; - case LMC_NET: - { + if (sc->if_type == LMC_NET) { struct net_device *dev = sc->lmc_device; /* - * They set a few basics because they don't use sync_ppp + * They set a few basics because they don't use HDLC */ dev->flags |= IFF_POINTOPOINT; - dev->hard_header_len = 0; dev->addr_len = 0; } - case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */ - { - } - default: - break; - } lmc_trace(sc->lmc_device, "lmc_proto_attach out"); } -// detach -void lmc_proto_detach(lmc_softc_t *sc) /*FOLD00*/ +int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) { - switch(sc->if_type){ - case LMC_PPP: - SPPP_detach(sc); - break; - case LMC_RAW: /* Tell someone we're detaching? */ - break; - default: - break; - } - + lmc_trace(sc->lmc_device, "lmc_proto_ioctl"); + if (sc->if_type == LMC_PPP) + return hdlc_ioctl(sc->lmc_device, ifr, cmd); + return -EOPNOTSUPP; } -// reopen -void lmc_proto_reopen(lmc_softc_t *sc) /*FOLD00*/ +int lmc_proto_open(lmc_softc_t *sc) { - lmc_trace(sc->lmc_device, "lmc_proto_reopen in"); - switch(sc->if_type){ - case LMC_PPP: - SPPP_reopen(sc); - break; - case LMC_RAW: /* Reset the interface after being down, prerape to receive packets again */ - break; - default: - break; - } - lmc_trace(sc->lmc_device, "lmc_proto_reopen out"); -} + int ret = 0; + lmc_trace(sc->lmc_device, "lmc_proto_open in"); -// ioctl -int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) /*FOLD00*/ -{ - lmc_trace(sc->lmc_device, "lmc_proto_ioctl out"); - switch(sc->if_type){ - case LMC_PPP: - return SPPP_do_ioctl (sc, ifr, cmd); - break; - default: - return -EOPNOTSUPP; - break; - } - lmc_trace(sc->lmc_device, "lmc_proto_ioctl out"); + if (sc->if_type == LMC_PPP) { + ret = hdlc_open(sc->lmc_device); + if (ret < 0) + printk(KERN_WARNING "%s: HDLC open failed: %d\n", + sc->name, ret); + } + + lmc_trace(sc->lmc_device, "lmc_proto_open out"); + return ret; } -// open -void lmc_proto_open(lmc_softc_t *sc) /*FOLD00*/ +void lmc_proto_close(lmc_softc_t *sc) { - int ret; + lmc_trace(sc->lmc_device, "lmc_proto_close in"); - lmc_trace(sc->lmc_device, "lmc_proto_open in"); - switch(sc->if_type){ - case LMC_PPP: - ret = SPPP_open(sc); - if(ret < 0) - printk("%s: syncPPP open failed: %d\n", sc->name, ret); - break; - case LMC_RAW: /* We're about to start getting packets! */ - break; - default: - break; - } - lmc_trace(sc->lmc_device, "lmc_proto_open out"); -} - -// close + if (sc->if_type == LMC_PPP) + hdlc_close(sc->lmc_device); -void lmc_proto_close(lmc_softc_t *sc) /*FOLD00*/ -{ - lmc_trace(sc->lmc_device, "lmc_proto_close in"); - switch(sc->if_type){ - case LMC_PPP: - SPPP_close(sc); - break; - case LMC_RAW: /* Interface going down */ - break; - default: - break; - } - lmc_trace(sc->lmc_device, "lmc_proto_close out"); + lmc_trace(sc->lmc_device, "lmc_proto_close out"); } __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ @@ -213,8 +102,8 @@ __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ lmc_trace(sc->lmc_device, "lmc_proto_type in"); switch(sc->if_type){ case LMC_PPP: - return htons(ETH_P_WAN_PPP); - break; + return hdlc_type_trans(skb, sc->lmc_device); + break; case LMC_NET: return htons(ETH_P_802_2); break; @@ -237,7 +126,6 @@ void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ case LMC_PPP: case LMC_NET: default: - skb->dev->last_rx = jiffies; netif_rx(skb); break; case LMC_RAW: @@ -245,4 +133,3 @@ void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ } lmc_trace(sc->lmc_device, "lmc_proto_netif out"); } - diff --git a/drivers/net/wan/lmc/lmc_proto.h b/drivers/net/wan/lmc/lmc_proto.h index ccaa69e8b3c..662148c5464 100644 --- a/drivers/net/wan/lmc/lmc_proto.h +++ b/drivers/net/wan/lmc/lmc_proto.h @@ -1,16 +1,18 @@ #ifndef _LMC_PROTO_H_ #define _LMC_PROTO_H_ -void lmc_proto_init(lmc_softc_t *sc); +#include <linux/hdlc.h> + void lmc_proto_attach(lmc_softc_t *sc); -void lmc_proto_detach(lmc_softc_t *sc); -void lmc_proto_reopen(lmc_softc_t *sc); int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd); -void lmc_proto_open(lmc_softc_t *sc); +int lmc_proto_open(lmc_softc_t *sc); void lmc_proto_close(lmc_softc_t *sc); __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb); void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb); -int lmc_skb_rawpackets(char *buf, char **start, off_t offset, int len, int unused); -#endif +static inline lmc_softc_t* dev_to_sc(struct net_device *dev) +{ + return (lmc_softc_t *)dev_to_hdlc(dev)->priv; +} +#endif diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h index 6d003a39bfa..a1d202d8ad6 100644 --- a/drivers/net/wan/lmc/lmc_var.h +++ b/drivers/net/wan/lmc/lmc_var.h @@ -1,8 +1,6 @@ #ifndef _LMC_VAR_H_ #define _LMC_VAR_H_ -/* $Id: lmc_var.h,v 1.17 2000/04/06 12:16:47 asj Exp $ */ - /* * Copyright (c) 1997-2000 LAN Media Corporation (LMC) * All rights reserved. www.lanmedia.com @@ -19,23 +17,6 @@ #include <linux/timer.h> -#ifndef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - -#define BITS_PER_LONG 32 - -#endif - /* * basic definitions used in lmc include files */ @@ -45,9 +26,6 @@ typedef struct lmc___media lmc_media_t; typedef struct lmc___ctl lmc_ctl_t; #define lmc_csrptr_t unsigned long -#define u_int16_t u16 -#define u_int8_t u8 -#define tulip_uint32_t u32 #define LMC_REG_RANGE 0x80 @@ -122,45 +100,45 @@ struct lmc_regfile_t { * used to define bits in the second tulip_desc_t field (length) * for the transmit descriptor -baz */ -#define LMC_TDES_FIRST_BUFFER_SIZE ((u_int32_t)(0x000007FF)) -#define LMC_TDES_SECOND_BUFFER_SIZE ((u_int32_t)(0x003FF800)) -#define LMC_TDES_HASH_FILTERING ((u_int32_t)(0x00400000)) -#define LMC_TDES_DISABLE_PADDING ((u_int32_t)(0x00800000)) -#define LMC_TDES_SECOND_ADDR_CHAINED ((u_int32_t)(0x01000000)) -#define LMC_TDES_END_OF_RING ((u_int32_t)(0x02000000)) -#define LMC_TDES_ADD_CRC_DISABLE ((u_int32_t)(0x04000000)) -#define LMC_TDES_SETUP_PACKET ((u_int32_t)(0x08000000)) -#define LMC_TDES_INVERSE_FILTERING ((u_int32_t)(0x10000000)) -#define LMC_TDES_FIRST_SEGMENT ((u_int32_t)(0x20000000)) -#define LMC_TDES_LAST_SEGMENT ((u_int32_t)(0x40000000)) -#define LMC_TDES_INTERRUPT_ON_COMPLETION ((u_int32_t)(0x80000000)) +#define LMC_TDES_FIRST_BUFFER_SIZE ((u32)(0x000007FF)) +#define LMC_TDES_SECOND_BUFFER_SIZE ((u32)(0x003FF800)) +#define LMC_TDES_HASH_FILTERING ((u32)(0x00400000)) +#define LMC_TDES_DISABLE_PADDING ((u32)(0x00800000)) +#define LMC_TDES_SECOND_ADDR_CHAINED ((u32)(0x01000000)) +#define LMC_TDES_END_OF_RING ((u32)(0x02000000)) +#define LMC_TDES_ADD_CRC_DISABLE ((u32)(0x04000000)) +#define LMC_TDES_SETUP_PACKET ((u32)(0x08000000)) +#define LMC_TDES_INVERSE_FILTERING ((u32)(0x10000000)) +#define LMC_TDES_FIRST_SEGMENT ((u32)(0x20000000)) +#define LMC_TDES_LAST_SEGMENT ((u32)(0x40000000)) +#define LMC_TDES_INTERRUPT_ON_COMPLETION ((u32)(0x80000000)) #define TDES_SECOND_BUFFER_SIZE_BIT_NUMBER 11 #define TDES_COLLISION_COUNT_BIT_NUMBER 3 /* Constants for the RCV descriptor RDES */ -#define LMC_RDES_OVERFLOW ((u_int32_t)(0x00000001)) -#define LMC_RDES_CRC_ERROR ((u_int32_t)(0x00000002)) -#define LMC_RDES_DRIBBLING_BIT ((u_int32_t)(0x00000004)) -#define LMC_RDES_REPORT_ON_MII_ERR ((u_int32_t)(0x00000008)) -#define LMC_RDES_RCV_WATCHDOG_TIMEOUT ((u_int32_t)(0x00000010)) -#define LMC_RDES_FRAME_TYPE ((u_int32_t)(0x00000020)) -#define LMC_RDES_COLLISION_SEEN ((u_int32_t)(0x00000040)) -#define LMC_RDES_FRAME_TOO_LONG ((u_int32_t)(0x00000080)) -#define LMC_RDES_LAST_DESCRIPTOR ((u_int32_t)(0x00000100)) -#define LMC_RDES_FIRST_DESCRIPTOR ((u_int32_t)(0x00000200)) -#define LMC_RDES_MULTICAST_FRAME ((u_int32_t)(0x00000400)) -#define LMC_RDES_RUNT_FRAME ((u_int32_t)(0x00000800)) -#define LMC_RDES_DATA_TYPE ((u_int32_t)(0x00003000)) -#define LMC_RDES_LENGTH_ERROR ((u_int32_t)(0x00004000)) -#define LMC_RDES_ERROR_SUMMARY ((u_int32_t)(0x00008000)) -#define LMC_RDES_FRAME_LENGTH ((u_int32_t)(0x3FFF0000)) -#define LMC_RDES_OWN_BIT ((u_int32_t)(0x80000000)) +#define LMC_RDES_OVERFLOW ((u32)(0x00000001)) +#define LMC_RDES_CRC_ERROR ((u32)(0x00000002)) +#define LMC_RDES_DRIBBLING_BIT ((u32)(0x00000004)) +#define LMC_RDES_REPORT_ON_MII_ERR ((u32)(0x00000008)) +#define LMC_RDES_RCV_WATCHDOG_TIMEOUT ((u32)(0x00000010)) +#define LMC_RDES_FRAME_TYPE ((u32)(0x00000020)) +#define LMC_RDES_COLLISION_SEEN ((u32)(0x00000040)) +#define LMC_RDES_FRAME_TOO_LONG ((u32)(0x00000080)) +#define LMC_RDES_LAST_DESCRIPTOR ((u32)(0x00000100)) +#define LMC_RDES_FIRST_DESCRIPTOR ((u32)(0x00000200)) +#define LMC_RDES_MULTICAST_FRAME ((u32)(0x00000400)) +#define LMC_RDES_RUNT_FRAME ((u32)(0x00000800)) +#define LMC_RDES_DATA_TYPE ((u32)(0x00003000)) +#define LMC_RDES_LENGTH_ERROR ((u32)(0x00004000)) +#define LMC_RDES_ERROR_SUMMARY ((u32)(0x00008000)) +#define LMC_RDES_FRAME_LENGTH ((u32)(0x3FFF0000)) +#define LMC_RDES_OWN_BIT ((u32)(0x80000000)) #define RDES_FRAME_LENGTH_BIT_NUMBER 16 -#define LMC_RDES_ERROR_MASK ( (u_int32_t)( \ +#define LMC_RDES_ERROR_MASK ( (u32)( \ LMC_RDES_OVERFLOW \ | LMC_RDES_DRIBBLING_BIT \ | LMC_RDES_REPORT_ON_MII_ERR \ @@ -172,37 +150,37 @@ struct lmc_regfile_t { */ typedef struct { - u_int32_t n; - u_int32_t m; - u_int32_t v; - u_int32_t x; - u_int32_t r; - u_int32_t f; - u_int32_t exact; + u32 n; + u32 m; + u32 v; + u32 x; + u32 r; + u32 f; + u32 exact; } lmc_av9110_t; /* * Common structure passed to the ioctl code. */ struct lmc___ctl { - u_int32_t cardtype; - u_int32_t clock_source; /* HSSI, T1 */ - u_int32_t clock_rate; /* T1 */ - u_int32_t crc_length; - u_int32_t cable_length; /* DS3 */ - u_int32_t scrambler_onoff; /* DS3 */ - u_int32_t cable_type; /* T1 */ - u_int32_t keepalive_onoff; /* protocol */ - u_int32_t ticks; /* ticks/sec */ + u32 cardtype; + u32 clock_source; /* HSSI, T1 */ + u32 clock_rate; /* T1 */ + u32 crc_length; + u32 cable_length; /* DS3 */ + u32 scrambler_onoff; /* DS3 */ + u32 cable_type; /* T1 */ + u32 keepalive_onoff; /* protocol */ + u32 ticks; /* ticks/sec */ union { lmc_av9110_t ssi; } cardspec; - u_int32_t circuit_type; /* T1 or E1 */ + u32 circuit_type; /* T1 or E1 */ }; /* - * Carefull, look at the data sheet, there's more to this + * Careful, look at the data sheet, there's more to this * structure than meets the eye. It should probably be: * * struct tulip_desc_t { @@ -244,108 +222,69 @@ struct lmc___media { #define STATCHECK 0xBEEFCAFE -/* Included in this structure are first - * - standard net_device_stats - * - some other counters used for debug and driver performance - * evaluation -baz - */ -struct lmc_statistics +struct lmc_extra_statistics { - unsigned long rx_packets; /* total packets received */ - unsigned long tx_packets; /* total packets transmitted */ - unsigned long rx_bytes; - unsigned long tx_bytes; - - unsigned long rx_errors; /* bad packets received */ - unsigned long tx_errors; /* packet transmit problems */ - unsigned long rx_dropped; /* no space in linux buffers */ - unsigned long tx_dropped; /* no space available in linux */ - unsigned long multicast; /* multicast packets received */ - unsigned long collisions; - - /* detailed rx_errors: */ - unsigned long rx_length_errors; - unsigned long rx_over_errors; /* receiver ring buff overflow */ - unsigned long rx_crc_errors; /* recved pkt with crc error */ - unsigned long rx_frame_errors; /* recv'd frame alignment error */ - unsigned long rx_fifo_errors; /* recv'r fifo overrun */ - unsigned long rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - unsigned long tx_aborted_errors; - unsigned long tx_carrier_errors; - unsigned long tx_fifo_errors; - unsigned long tx_heartbeat_errors; - unsigned long tx_window_errors; - - /* for cslip etc */ - unsigned long rx_compressed; - unsigned long tx_compressed; - - /* ------------------------------------- - * Custom stats & counters follow -baz */ - u_int32_t version_size; - u_int32_t lmc_cardtype; - - u_int32_t tx_ProcTimeout; - u_int32_t tx_IntTimeout; - u_int32_t tx_NoCompleteCnt; - u_int32_t tx_MaxXmtsB4Int; - u_int32_t tx_TimeoutCnt; - u_int32_t tx_OutOfSyncPtr; - u_int32_t tx_tbusy0; - u_int32_t tx_tbusy1; - u_int32_t tx_tbusy_calls; - u_int32_t resetCount; - u_int32_t lmc_txfull; - u_int32_t tbusy; - u_int32_t dirtyTx; - u_int32_t lmc_next_tx; - u_int32_t otherTypeCnt; - u_int32_t lastType; - u_int32_t lastTypeOK; - u_int32_t txLoopCnt; - u_int32_t usedXmtDescripCnt; - u_int32_t txIndexCnt; - u_int32_t rxIntLoopCnt; - - u_int32_t rx_SmallPktCnt; - u_int32_t rx_BadPktSurgeCnt; - u_int32_t rx_BuffAllocErr; - u_int32_t tx_lossOfClockCnt; - - /* T1 error counters */ - u_int32_t framingBitErrorCount; - u_int32_t lineCodeViolationCount; - - u_int32_t lossOfFrameCount; - u_int32_t changeOfFrameAlignmentCount; - u_int32_t severelyErroredFrameCount; - - u_int32_t check; + u32 version_size; + u32 lmc_cardtype; + + u32 tx_ProcTimeout; + u32 tx_IntTimeout; + u32 tx_NoCompleteCnt; + u32 tx_MaxXmtsB4Int; + u32 tx_TimeoutCnt; + u32 tx_OutOfSyncPtr; + u32 tx_tbusy0; + u32 tx_tbusy1; + u32 tx_tbusy_calls; + u32 resetCount; + u32 lmc_txfull; + u32 tbusy; + u32 dirtyTx; + u32 lmc_next_tx; + u32 otherTypeCnt; + u32 lastType; + u32 lastTypeOK; + u32 txLoopCnt; + u32 usedXmtDescripCnt; + u32 txIndexCnt; + u32 rxIntLoopCnt; + + u32 rx_SmallPktCnt; + u32 rx_BadPktSurgeCnt; + u32 rx_BuffAllocErr; + u32 tx_lossOfClockCnt; + + /* T1 error counters */ + u32 framingBitErrorCount; + u32 lineCodeViolationCount; + + u32 lossOfFrameCount; + u32 changeOfFrameAlignmentCount; + u32 severelyErroredFrameCount; + + u32 check; }; - typedef struct lmc_xinfo { - u_int32_t Magic0; /* BEEFCAFE */ + u32 Magic0; /* BEEFCAFE */ - u_int32_t PciCardType; - u_int32_t PciSlotNumber; /* PCI slot number */ + u32 PciCardType; + u32 PciSlotNumber; /* PCI slot number */ - u_int16_t DriverMajorVersion; - u_int16_t DriverMinorVersion; - u_int16_t DriverSubVersion; + u16 DriverMajorVersion; + u16 DriverMinorVersion; + u16 DriverSubVersion; - u_int16_t XilinxRevisionNumber; - u_int16_t MaxFrameSize; + u16 XilinxRevisionNumber; + u16 MaxFrameSize; - u_int16_t t1_alarm1_status; - u_int16_t t1_alarm2_status; + u16 t1_alarm1_status; + u16 t1_alarm2_status; - int link_status; - u_int32_t mii_reg16; + int link_status; + u32 mii_reg16; - u_int32_t Magic1; /* DEADBEEF */ + u32 Magic1; /* DEADBEEF */ } LMC_XINFO; @@ -353,23 +292,22 @@ typedef struct lmc_xinfo { * forward decl */ struct lmc___softc { - void *if_ptr; /* General purpose pointer (used by SPPP) */ char *name; u8 board_idx; - struct lmc_statistics stats; - struct net_device *lmc_device; + struct lmc_extra_statistics extra_stats; + struct net_device *lmc_device; int hang, rxdesc, bad_packet, some_counter; - u_int32_t txgo; + u32 txgo; struct lmc_regfile_t lmc_csrs; - volatile u_int32_t lmc_txtick; - volatile u_int32_t lmc_rxtick; - u_int32_t lmc_flags; - u_int32_t lmc_intrmask; /* our copy of csr_intr */ - u_int32_t lmc_cmdmode; /* our copy of csr_cmdmode */ - u_int32_t lmc_busmode; /* our copy of csr_busmode */ - u_int32_t lmc_gpio_io; /* state of in/out settings */ - u_int32_t lmc_gpio; /* state of outputs */ + volatile u32 lmc_txtick; + volatile u32 lmc_rxtick; + u32 lmc_flags; + u32 lmc_intrmask; /* our copy of csr_intr */ + u32 lmc_cmdmode; /* our copy of csr_cmdmode */ + u32 lmc_busmode; /* our copy of csr_busmode */ + u32 lmc_gpio_io; /* state of in/out settings */ + u32 lmc_gpio; /* state of outputs */ struct sk_buff* lmc_txq[LMC_TXDESCS]; struct sk_buff* lmc_rxq[LMC_RXDESCS]; volatile @@ -381,42 +319,41 @@ struct lmc___softc { unsigned int lmc_taint_tx, lmc_taint_rx; int lmc_tx_start, lmc_txfull; int lmc_txbusy; - u_int16_t lmc_miireg16; + u16 lmc_miireg16; int lmc_ok; int last_link_status; int lmc_cardtype; - u_int32_t last_frameerr; + u32 last_frameerr; lmc_media_t *lmc_media; struct timer_list timer; lmc_ctl_t ictl; - u_int32_t TxDescriptControlInit; + u32 TxDescriptControlInit; int tx_TimeoutInd; /* additional driver state */ int tx_TimeoutDisplay; unsigned int lastlmc_taint_tx; int lasttx_packets; - u_int32_t tx_clockState; - u_int32_t lmc_crcSize; - LMC_XINFO lmc_xinfo; + u32 tx_clockState; + u32 lmc_crcSize; + LMC_XINFO lmc_xinfo; char lmc_yel, lmc_blue, lmc_red; /* for T1 and DS3 */ - char lmc_timing; /* for HSSI and SSI */ - int got_irq; + char lmc_timing; /* for HSSI and SSI */ + int got_irq; - char last_led_err[4]; + char last_led_err[4]; - u32 last_int; - u32 num_int; + u32 last_int; + u32 num_int; spinlock_t lmc_lock; - u_int16_t if_type; /* PPP or NET */ - struct ppp_device *pd; + u16 if_type; /* HDLC/PPP or NET */ - /* Failure cases */ - u8 failed_ring; - u8 failed_recv_alloc; + /* Failure cases */ + u8 failed_ring; + u8 failed_recv_alloc; - /* Structure check */ - u32 check; + /* Structure check */ + u32 check; }; #define LMC_PCI_TIME 1 @@ -443,7 +380,7 @@ struct lmc___softc { /* CSR6 settings */ #define OPERATION_MODE 0x00000200 /* Full Duplex */ #define PROMISC_MODE 0x00000040 /* Promiscuous Mode */ -#define RECIEVE_ALL 0x40000000 /* Recieve All */ +#define RECEIVE_ALL 0x40000000 /* Receive All */ #define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames */ /* Dec control registers CSR6 as well */ @@ -461,7 +398,7 @@ struct lmc___softc { #define TULIP_CMD_RECEIVEALL 0x40000000L /* (RW) Receivel all frames? */ #define TULIP_CMD_MUSTBEONE 0x02000000L /* (RW) Must Be One (21140) */ #define TULIP_CMD_TXTHRSHLDCTL 0x00400000L /* (RW) Transmit Threshold Mode (21140) */ -#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Foward (21140) */ +#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Forward (21140) */ #define TULIP_CMD_NOHEARTBEAT 0x00080000L /* (RW) No Heartbeat (21140) */ #define TULIP_CMD_PORTSELECT 0x00040000L /* (RW) Post Select (100Mb) (21140) */ #define TULIP_CMD_FULLDUPLEX 0x00000200L /* (RW) Full Duplex Mode */ @@ -512,8 +449,8 @@ struct lmc___softc { | TULIP_STS_TXUNDERFLOW\ | TULIP_STS_RXSTOPPED ) -#define DESC_OWNED_BY_SYSTEM ((u_int32_t)(0x00000000)) -#define DESC_OWNED_BY_DC21X4 ((u_int32_t)(0x80000000)) +#define DESC_OWNED_BY_SYSTEM ((u32)(0x00000000)) +#define DESC_OWNED_BY_DC21X4 ((u32)(0x80000000)) #ifndef TULIP_CMD_RECEIVEALL #define TULIP_CMD_RECEIVEALL 0x40000000L @@ -525,46 +462,9 @@ struct lmc___softc { #define LMC_ADAP_SSI 4 #define LMC_ADAP_T1 5 -#define HDLC_HDR_LEN 4 -#define HDLC_ADDR_LEN 1 -#define HDLC_SLARP 0x8035 #define LMC_MTU 1500 -#define SLARP_LINECHECK 2 #define LMC_CRC_LEN_16 2 /* 16-bit CRC */ #define LMC_CRC_LEN_32 4 -#ifdef LMC_HDLC -/* definition of an hdlc header. */ -struct hdlc_hdr -{ - u8 address; - u8 control; - u16 type; -}; - -/* definition of a slarp header. */ -struct slarp -{ - long code; - union sl - { - struct - { - ulong address; - ulong mask; - ushort unused; - } add; - struct - { - ulong mysequence; - ulong yoursequence; - ushort reliability; - ulong time; - } chk; - } t; -}; -#endif /* LMC_HDLC */ - - #endif /* _LMC_VAR_H_ */ diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 0a566b0daac..315bf09d6a2 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -16,8 +16,11 @@ * SDL Inc. PPP/HDLC/CISCO driver */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> +#include <linux/capability.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/fcntl.h> @@ -53,7 +56,7 @@ static const char* devname = "RISCom/N2"; #define NEED_SCA_MSCI_INTR #define MAX_TX_BUFFERS 10 -static char *hw = NULL; /* pointer to hw=xxx command line string */ +static char *hw; /* pointer to hw=xxx command line string */ /* RISCom/N2 Board Registers */ @@ -145,7 +148,6 @@ static card_t **new_card = &first_card; &(card)->ports[port] : NULL) - static __inline__ u8 sca_get_page(card_t *card) { return inb(card->io + N2_PSR) & PSR_PAGEBITS; @@ -159,9 +161,7 @@ static __inline__ void openwin(card_t *card, u8 page) } - -#include "hd6457x.c" - +#include "hd64570.c" static void n2_set_iface(port_t *port) @@ -284,7 +284,7 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; @@ -327,7 +327,13 @@ static void n2_destroy_card(card_t *card) kfree(card); } - +static const struct net_device_ops n2_ops = { + .ndo_open = n2_open, + .ndo_stop = n2_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = n2_ioctl, +}; static int __init n2_run(unsigned long io, unsigned long irq, unsigned long winbase, long valid0, long valid1) @@ -337,57 +343,55 @@ static int __init n2_run(unsigned long io, unsigned long irq, int i; if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) { - printk(KERN_ERR "n2: invalid I/O port value\n"); + pr_err("invalid I/O port value\n"); return -ENODEV; } if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ { - printk(KERN_ERR "n2: invalid IRQ value\n"); + pr_err("invalid IRQ value\n"); return -ENODEV; } if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) { - printk(KERN_ERR "n2: invalid RAM value\n"); + pr_err("invalid RAM value\n"); return -ENODEV; } card = kzalloc(sizeof(card_t), GFP_KERNEL); - if (card == NULL) { - printk(KERN_ERR "n2: unable to allocate memory\n"); + if (card == NULL) return -ENOBUFS; - } card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); if (!card->ports[0].dev || !card->ports[1].dev) { - printk(KERN_ERR "n2: unable to allocate memory\n"); + pr_err("unable to allocate memory\n"); n2_destroy_card(card); return -ENOMEM; } if (!request_region(io, N2_IOPORTS, devname)) { - printk(KERN_ERR "n2: I/O port region in use\n"); + pr_err("I/O port region in use\n"); n2_destroy_card(card); return -EBUSY; } card->io = io; - if (request_irq(irq, &sca_intr, 0, devname, card)) { - printk(KERN_ERR "n2: could not allocate IRQ\n"); + if (request_irq(irq, sca_intr, 0, devname, card)) { + pr_err("could not allocate IRQ\n"); n2_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->irq = irq; if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) { - printk(KERN_ERR "n2: could not request RAM window\n"); + pr_err("could not request RAM window\n"); n2_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->phy_winbase = winbase; card->winbase = ioremap(winbase, USE_WINDOWSIZE); if (!card->winbase) { - printk(KERN_ERR "n2: ioremap() failed\n"); + pr_err("ioremap() failed\n"); n2_destroy_card(card); return -EFAULT; } @@ -409,7 +413,7 @@ static int __init n2_run(unsigned long io, unsigned long irq, break; default: - printk(KERN_ERR "n2: invalid window size\n"); + pr_err("invalid window size\n"); n2_destroy_card(card); return -ENODEV; } @@ -429,12 +433,12 @@ static int __init n2_run(unsigned long io, unsigned long irq, card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) * (card->tx_ring_buffers + card->rx_ring_buffers); - printk(KERN_INFO "n2: RISCom/N2 %u KB RAM, IRQ%u, " - "using %u TX + %u RX packets rings\n", card->ram_size / 1024, - card->irq, card->tx_ring_buffers, card->rx_ring_buffers); + pr_info("RISCom/N2 %u KB RAM, IRQ%u, using %u TX + %u RX packets rings\n", + card->ram_size / 1024, card->irq, + card->tx_ring_buffers, card->rx_ring_buffers); if (card->tx_ring_buffers < 1) { - printk(KERN_ERR "n2: RAM test failed\n"); + pr_err("RAM test failed\n"); n2_destroy_card(card); return -EIO; } @@ -463,25 +467,21 @@ static int __init n2_run(unsigned long io, unsigned long irq, dev->mem_start = winbase; dev->mem_end = winbase + USE_WINDOWSIZE - 1; dev->tx_queue_len = 50; - dev->do_ioctl = n2_ioctl; - dev->open = n2_open; - dev->stop = n2_close; + dev->netdev_ops = &n2_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; port->card = card; if (register_hdlc_device(dev)) { - printk(KERN_WARNING "n2: unable to register hdlc " - "device\n"); + pr_warn("unable to register hdlc device\n"); port->card = NULL; n2_destroy_card(card); return -ENOBUFS; } - sca_init_sync_port(port); /* Set up SCA memory */ + sca_init_port(port); /* Set up SCA memory */ - printk(KERN_INFO "%s: RISCom/N2 node %d\n", - dev->name, port->phy_node); + netdev_info(dev, "RISCom/N2 node %d\n", port->phy_node); } *new_card = card; @@ -496,12 +496,12 @@ static int __init n2_init(void) { if (hw==NULL) { #ifdef MODULE - printk(KERN_INFO "n2: no card initialized\n"); + pr_info("no card initialized\n"); #endif return -EINVAL; /* no parameters specified, abort */ } - printk(KERN_INFO "%s\n", version); + pr_info("%s\n", version); do { unsigned long io, irq, ram; @@ -539,7 +539,7 @@ static int __init n2_init(void) return first_card ? 0 : -EINVAL; }while(*hw++ == ':'); - printk(KERN_ERR "n2: invalid hardware parameters\n"); + pr_err("invalid hardware parameters\n"); return first_card ? 0 : -EINVAL; } diff --git a/drivers/net/wan/pc300-falc-lh.h b/drivers/net/wan/pc300-falc-lh.h deleted file mode 100644 index 01ed23ca76c..00000000000 --- a/drivers/net/wan/pc300-falc-lh.h +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * falc.h Description of the Siemens FALC T1/E1 framer. - * - * Author: Ivan Passos <ivan@cyclades.com> - * - * Copyright: (c) 2000-2001 Cyclades Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * $Log: falc-lh.h,v $ - * Revision 3.1 2001/06/15 12:41:10 regina - * upping major version number - * - * Revision 1.1.1.1 2001/06/13 20:24:47 daniela - * PC300 initial CVS version (3.4.0-pre1) - * - * Revision 1.1 2000/05/15 ivan - * Included DJA bits for the LIM2 register. - * - * Revision 1.0 2000/02/22 ivan - * Initial version. - * - */ - -#ifndef _FALC_LH_H -#define _FALC_LH_H - -#define NUM_OF_T1_CHANNELS 24 -#define NUM_OF_E1_CHANNELS 32 - -/*>>>>>>>>>>>>>>>>> FALC Register Bits (Transmit Mode) <<<<<<<<<<<<<<<<<<< */ - -/* CMDR (Command Register) - ---------------- E1 & T1 ------------------------------ */ -#define CMDR_RMC 0x80 -#define CMDR_RRES 0x40 -#define CMDR_XREP 0x20 -#define CMDR_XRES 0x10 -#define CMDR_XHF 0x08 -#define CMDR_XTF 0x04 -#define CMDR_XME 0x02 -#define CMDR_SRES 0x01 - -/* MODE (Mode Register) - ----------------- E1 & T1 ----------------------------- */ -#define MODE_MDS2 0x80 -#define MODE_MDS1 0x40 -#define MODE_MDS0 0x20 -#define MODE_BRAC 0x10 -#define MODE_HRAC 0x08 - -/* IPC (Interrupt Port Configuration) - ----------------- E1 & T1 ----------------------------- */ -#define IPC_VIS 0x80 -#define IPC_SCI 0x04 -#define IPC_IC1 0x02 -#define IPC_IC0 0x01 - -/* CCR1 (Common Configuration Register 1) - ----------------- E1 & T1 ----------------------------- */ -#define CCR1_SFLG 0x80 -#define CCR1_XTS16RA 0x40 -#define CCR1_BRM 0x40 -#define CCR1_CASSYM 0x20 -#define CCR1_EDLX 0x20 -#define CCR1_EITS 0x10 -#define CCR1_ITF 0x08 -#define CCR1_RFT1 0x02 -#define CCR1_RFT0 0x01 - -/* CCR3 (Common Configuration Register 3) - ---------------- E1 & T1 ------------------------------ */ - -#define CCR3_PRE1 0x80 -#define CCR3_PRE0 0x40 -#define CCR3_EPT 0x20 -#define CCR3_RADD 0x10 -#define CCR3_RCRC 0x04 -#define CCR3_XCRC 0x02 - - -/* RTR1-4 (Receive Timeslot Register 1-4) - ---------------- E1 & T1 ------------------------------ */ - -#define RTR1_TS0 0x80 -#define RTR1_TS1 0x40 -#define RTR1_TS2 0x20 -#define RTR1_TS3 0x10 -#define RTR1_TS4 0x08 -#define RTR1_TS5 0x04 -#define RTR1_TS6 0x02 -#define RTR1_TS7 0x01 - -#define RTR2_TS8 0x80 -#define RTR2_TS9 0x40 -#define RTR2_TS10 0x20 -#define RTR2_TS11 0x10 -#define RTR2_TS12 0x08 -#define RTR2_TS13 0x04 -#define RTR2_TS14 0x02 -#define RTR2_TS15 0x01 - -#define RTR3_TS16 0x80 -#define RTR3_TS17 0x40 -#define RTR3_TS18 0x20 -#define RTR3_TS19 0x10 -#define RTR3_TS20 0x08 -#define RTR3_TS21 0x04 -#define RTR3_TS22 0x02 -#define RTR3_TS23 0x01 - -#define RTR4_TS24 0x80 -#define RTR4_TS25 0x40 -#define RTR4_TS26 0x20 -#define RTR4_TS27 0x10 -#define RTR4_TS28 0x08 -#define RTR4_TS29 0x04 -#define RTR4_TS30 0x02 -#define RTR4_TS31 0x01 - - -/* TTR1-4 (Transmit Timeslot Register 1-4) - ---------------- E1 & T1 ------------------------------ */ - -#define TTR1_TS0 0x80 -#define TTR1_TS1 0x40 -#define TTR1_TS2 0x20 -#define TTR1_TS3 0x10 -#define TTR1_TS4 0x08 -#define TTR1_TS5 0x04 -#define TTR1_TS6 0x02 -#define TTR1_TS7 0x01 - -#define TTR2_TS8 0x80 -#define TTR2_TS9 0x40 -#define TTR2_TS10 0x20 -#define TTR2_TS11 0x10 -#define TTR2_TS12 0x08 -#define TTR2_TS13 0x04 -#define TTR2_TS14 0x02 -#define TTR2_TS15 0x01 - -#define TTR3_TS16 0x80 -#define TTR3_TS17 0x40 -#define TTR3_TS18 0x20 -#define TTR3_TS19 0x10 -#define TTR3_TS20 0x08 -#define TTR3_TS21 0x04 -#define TTR3_TS22 0x02 -#define TTR3_TS23 0x01 - -#define TTR4_TS24 0x80 -#define TTR4_TS25 0x40 -#define TTR4_TS26 0x20 -#define TTR4_TS27 0x10 -#define TTR4_TS28 0x08 -#define TTR4_TS29 0x04 -#define TTR4_TS30 0x02 -#define TTR4_TS31 0x01 - - - -/* IMR0-4 (Interrupt Mask Register 0-4) - - ----------------- E1 & T1 ----------------------------- */ - -#define IMR0_RME 0x80 -#define IMR0_RFS 0x40 -#define IMR0_T8MS 0x20 -#define IMR0_ISF 0x20 -#define IMR0_RMB 0x10 -#define IMR0_CASC 0x08 -#define IMR0_RSC 0x08 -#define IMR0_CRC6 0x04 -#define IMR0_CRC4 0x04 -#define IMR0_PDEN 0x02 -#define IMR0_RPF 0x01 - -#define IMR1_CASE 0x80 -#define IMR1_RDO 0x40 -#define IMR1_ALLS 0x20 -#define IMR1_XDU 0x10 -#define IMR1_XMB 0x08 -#define IMR1_XLSC 0x02 -#define IMR1_XPR 0x01 -#define IMR1_LLBSC 0x80 - -#define IMR2_FAR 0x80 -#define IMR2_LFA 0x40 -#define IMR2_MFAR 0x20 -#define IMR2_T400MS 0x10 -#define IMR2_LMFA 0x10 -#define IMR2_AIS 0x08 -#define IMR2_LOS 0x04 -#define IMR2_RAR 0x02 -#define IMR2_RA 0x01 - -#define IMR3_ES 0x80 -#define IMR3_SEC 0x40 -#define IMR3_LMFA16 0x20 -#define IMR3_AIS16 0x10 -#define IMR3_RA16 0x08 -#define IMR3_API 0x04 -#define IMR3_XSLP 0x20 -#define IMR3_XSLN 0x10 -#define IMR3_LLBSC 0x08 -#define IMR3_XRS 0x04 -#define IMR3_SLN 0x02 -#define IMR3_SLP 0x01 - -#define IMR4_LFA 0x80 -#define IMR4_FER 0x40 -#define IMR4_CER 0x20 -#define IMR4_AIS 0x10 -#define IMR4_LOS 0x08 -#define IMR4_CVE 0x04 -#define IMR4_SLIP 0x02 -#define IMR4_EBE 0x01 - -/* FMR0-5 for E1 and T1 (Framer Mode Register ) */ - -#define FMR0_XC1 0x80 -#define FMR0_XC0 0x40 -#define FMR0_RC1 0x20 -#define FMR0_RC0 0x10 -#define FMR0_EXTD 0x08 -#define FMR0_ALM 0x04 -#define E1_FMR0_FRS 0x02 -#define T1_FMR0_FRS 0x08 -#define FMR0_SRAF 0x04 -#define FMR0_EXLS 0x02 -#define FMR0_SIM 0x01 - -#define FMR1_MFCS 0x80 -#define FMR1_AFR 0x40 -#define FMR1_ENSA 0x20 -#define FMR1_CTM 0x80 -#define FMR1_SIGM 0x40 -#define FMR1_EDL 0x20 -#define FMR1_PMOD 0x10 -#define FMR1_XFS 0x08 -#define FMR1_CRC 0x08 -#define FMR1_ECM 0x04 -#define FMR1_IMOD 0x02 -#define FMR1_XAIS 0x01 - -#define FMR2_RFS1 0x80 -#define FMR2_RFS0 0x40 -#define FMR2_MCSP 0x40 -#define FMR2_RTM 0x20 -#define FMR2_SSP 0x20 -#define FMR2_DAIS 0x10 -#define FMR2_SAIS 0x08 -#define FMR2_PLB 0x04 -#define FMR2_AXRA 0x02 -#define FMR2_ALMF 0x01 -#define FMR2_EXZE 0x01 - -#define LOOP_RTM 0x40 -#define LOOP_SFM 0x40 -#define LOOP_ECLB 0x20 -#define LOOP_CLA 0x1f - -/*--------------------- E1 ----------------------------*/ -#define FMR3_XLD 0x20 -#define FMR3_XLU 0x10 - -/*--------------------- T1 ----------------------------*/ -#define FMR4_AIS3 0x80 -#define FMR4_TM 0x40 -#define FMR4_XRA 0x20 -#define FMR4_SSC1 0x10 -#define FMR4_SSC0 0x08 -#define FMR4_AUTO 0x04 -#define FMR4_FM1 0x02 -#define FMR4_FM0 0x01 - -#define FMR5_SRS 0x80 -#define FMR5_EIBR 0x40 -#define FMR5_XLD 0x20 -#define FMR5_XLU 0x10 - - -/* LOOP (Channel Loop Back) - - ------------------ E1 & T1 ---------------------------- */ - -#define LOOP_SFM 0x40 -#define LOOP_ECLB 0x20 -#define LOOP_CLA4 0x10 -#define LOOP_CLA3 0x08 -#define LOOP_CLA2 0x04 -#define LOOP_CLA1 0x02 -#define LOOP_CLA0 0x01 - - - -/* XSW (Transmit Service Word Pulseframe) - - ------------------- E1 --------------------------- */ - -#define XSW_XSIS 0x80 -#define XSW_XTM 0x40 -#define XSW_XRA 0x20 -#define XSW_XY0 0x10 -#define XSW_XY1 0x08 -#define XSW_XY2 0x04 -#define XSW_XY3 0x02 -#define XSW_XY4 0x01 - - -/* XSP (Transmit Spare Bits) - - ------------------- E1 --------------------------- */ - -#define XSP_XAP 0x80 -#define XSP_CASEN 0x40 -#define XSP_TT0 0x20 -#define XSP_EBP 0x10 -#define XSP_AXS 0x08 -#define XSP_XSIF 0x04 -#define XSP_XS13 0x02 -#define XSP_XS15 0x01 - - -/* XC0/1 (Transmit Control 0/1) - ------------------ E1 & T1 ---------------------------- */ - -#define XC0_SA8E 0x80 -#define XC0_SA7E 0x40 -#define XC0_SA6E 0x20 -#define XC0_SA5E 0x10 -#define XC0_SA4E 0x08 -#define XC0_BRM 0x80 -#define XC0_MFBS 0x40 -#define XC0_SFRZ 0x10 -#define XC0_XCO2 0x04 -#define XC0_XCO1 0x02 -#define XC0_XCO0 0x01 - -#define XC1_XTO5 0x20 -#define XC1_XTO4 0x10 -#define XC1_XTO3 0x08 -#define XC1_XTO2 0x04 -#define XC1_XTO1 0x02 -#define XC1_XTO0 0x01 - - -/* RC0/1 (Receive Control 0/1) - ------------------ E1 & T1 ---------------------------- */ - -#define RC0_SICS 0x40 -#define RC0_CRCI 0x20 -#define RC0_XCRCI 0x10 -#define RC0_RDIS 0x08 -#define RC0_RCO2 0x04 -#define RC0_RCO1 0x02 -#define RC0_RCO0 0x01 - -#define RC1_SWD 0x80 -#define RC1_ASY4 0x40 -#define RC1_RRAM 0x40 -#define RC1_RTO5 0x20 -#define RC1_RTO4 0x10 -#define RC1_RTO3 0x08 -#define RC1_RTO2 0x04 -#define RC1_RTO1 0x02 -#define RC1_RTO0 0x01 - - - -/* XPM0-2 (Transmit Pulse Mask 0-2) - --------------------- E1 & T1 ------------------------- */ - -#define XPM0_XP12 0x80 -#define XPM0_XP11 0x40 -#define XPM0_XP10 0x20 -#define XPM0_XP04 0x10 -#define XPM0_XP03 0x08 -#define XPM0_XP02 0x04 -#define XPM0_XP01 0x02 -#define XPM0_XP00 0x01 - -#define XPM1_XP30 0x80 -#define XPM1_XP24 0x40 -#define XPM1_XP23 0x20 -#define XPM1_XP22 0x10 -#define XPM1_XP21 0x08 -#define XPM1_XP20 0x04 -#define XPM1_XP14 0x02 -#define XPM1_XP13 0x01 - -#define XPM2_XLHP 0x80 -#define XPM2_XLT 0x40 -#define XPM2_DAXLT 0x20 -#define XPM2_XP34 0x08 -#define XPM2_XP33 0x04 -#define XPM2_XP32 0x02 -#define XPM2_XP31 0x01 - - -/* TSWM (Transparent Service Word Mask) - ------------------ E1 ---------------------------- */ - -#define TSWM_TSIS 0x80 -#define TSWM_TSIF 0x40 -#define TSWM_TRA 0x20 -#define TSWM_TSA4 0x10 -#define TSWM_TSA5 0x08 -#define TSWM_TSA6 0x04 -#define TSWM_TSA7 0x02 -#define TSWM_TSA8 0x01 - -/* IDLE <Idle Channel Code Register> - - ------------------ E1 & T1 ----------------------- */ - -#define IDLE_IDL7 0x80 -#define IDLE_IDL6 0x40 -#define IDLE_IDL5 0x20 -#define IDLE_IDL4 0x10 -#define IDLE_IDL3 0x08 -#define IDLE_IDL2 0x04 -#define IDLE_IDL1 0x02 -#define IDLE_IDL0 0x01 - - -/* XSA4-8 <Transmit SA4-8 Register(Read/Write) > - -------------------E1 ----------------------------- */ - -#define XSA4_XS47 0x80 -#define XSA4_XS46 0x40 -#define XSA4_XS45 0x20 -#define XSA4_XS44 0x10 -#define XSA4_XS43 0x08 -#define XSA4_XS42 0x04 -#define XSA4_XS41 0x02 -#define XSA4_XS40 0x01 - -#define XSA5_XS57 0x80 -#define XSA5_XS56 0x40 -#define XSA5_XS55 0x20 -#define XSA5_XS54 0x10 -#define XSA5_XS53 0x08 -#define XSA5_XS52 0x04 -#define XSA5_XS51 0x02 -#define XSA5_XS50 0x01 - -#define XSA6_XS67 0x80 -#define XSA6_XS66 0x40 -#define XSA6_XS65 0x20 -#define XSA6_XS64 0x10 -#define XSA6_XS63 0x08 -#define XSA6_XS62 0x04 -#define XSA6_XS61 0x02 -#define XSA6_XS60 0x01 - -#define XSA7_XS77 0x80 -#define XSA7_XS76 0x40 -#define XSA7_XS75 0x20 -#define XSA7_XS74 0x10 -#define XSA7_XS73 0x08 -#define XSA7_XS72 0x04 -#define XSA7_XS71 0x02 -#define XSA7_XS70 0x01 - -#define XSA8_XS87 0x80 -#define XSA8_XS86 0x40 -#define XSA8_XS85 0x20 -#define XSA8_XS84 0x10 -#define XSA8_XS83 0x08 -#define XSA8_XS82 0x04 -#define XSA8_XS81 0x02 -#define XSA8_XS80 0x01 - - -/* XDL1-3 (Transmit DL-Bit Register1-3 (read/write)) - ----------------------- T1 --------------------- */ - -#define XDL1_XDL17 0x80 -#define XDL1_XDL16 0x40 -#define XDL1_XDL15 0x20 -#define XDL1_XDL14 0x10 -#define XDL1_XDL13 0x08 -#define XDL1_XDL12 0x04 -#define XDL1_XDL11 0x02 -#define XDL1_XDL10 0x01 - -#define XDL2_XDL27 0x80 -#define XDL2_XDL26 0x40 -#define XDL2_XDL25 0x20 -#define XDL2_XDL24 0x10 -#define XDL2_XDL23 0x08 -#define XDL2_XDL22 0x04 -#define XDL2_XDL21 0x02 -#define XDL2_XDL20 0x01 - -#define XDL3_XDL37 0x80 -#define XDL3_XDL36 0x40 -#define XDL3_XDL35 0x20 -#define XDL3_XDL34 0x10 -#define XDL3_XDL33 0x08 -#define XDL3_XDL32 0x04 -#define XDL3_XDL31 0x02 -#define XDL3_XDL30 0x01 - - -/* ICB1-4 (Idle Channel Register 1-4) - ------------------ E1 ---------------------------- */ - -#define E1_ICB1_IC0 0x80 -#define E1_ICB1_IC1 0x40 -#define E1_ICB1_IC2 0x20 -#define E1_ICB1_IC3 0x10 -#define E1_ICB1_IC4 0x08 -#define E1_ICB1_IC5 0x04 -#define E1_ICB1_IC6 0x02 -#define E1_ICB1_IC7 0x01 - -#define E1_ICB2_IC8 0x80 -#define E1_ICB2_IC9 0x40 -#define E1_ICB2_IC10 0x20 -#define E1_ICB2_IC11 0x10 -#define E1_ICB2_IC12 0x08 -#define E1_ICB2_IC13 0x04 -#define E1_ICB2_IC14 0x02 -#define E1_ICB2_IC15 0x01 - -#define E1_ICB3_IC16 0x80 -#define E1_ICB3_IC17 0x40 -#define E1_ICB3_IC18 0x20 -#define E1_ICB3_IC19 0x10 -#define E1_ICB3_IC20 0x08 -#define E1_ICB3_IC21 0x04 -#define E1_ICB3_IC22 0x02 -#define E1_ICB3_IC23 0x01 - -#define E1_ICB4_IC24 0x80 -#define E1_ICB4_IC25 0x40 -#define E1_ICB4_IC26 0x20 -#define E1_ICB4_IC27 0x10 -#define E1_ICB4_IC28 0x08 -#define E1_ICB4_IC29 0x04 -#define E1_ICB4_IC30 0x02 -#define E1_ICB4_IC31 0x01 - -/* ICB1-4 (Idle Channel Register 1-4) - ------------------ T1 ---------------------------- */ - -#define T1_ICB1_IC1 0x80 -#define T1_ICB1_IC2 0x40 -#define T1_ICB1_IC3 0x20 -#define T1_ICB1_IC4 0x10 -#define T1_ICB1_IC5 0x08 -#define T1_ICB1_IC6 0x04 -#define T1_ICB1_IC7 0x02 -#define T1_ICB1_IC8 0x01 - -#define T1_ICB2_IC9 0x80 -#define T1_ICB2_IC10 0x40 -#define T1_ICB2_IC11 0x20 -#define T1_ICB2_IC12 0x10 -#define T1_ICB2_IC13 0x08 -#define T1_ICB2_IC14 0x04 -#define T1_ICB2_IC15 0x02 -#define T1_ICB2_IC16 0x01 - -#define T1_ICB3_IC17 0x80 -#define T1_ICB3_IC18 0x40 -#define T1_ICB3_IC19 0x20 -#define T1_ICB3_IC20 0x10 -#define T1_ICB3_IC21 0x08 -#define T1_ICB3_IC22 0x04 -#define T1_ICB3_IC23 0x02 -#define T1_ICB3_IC24 0x01 - -/* FMR3 (Framer Mode Register 3) - --------------------E1------------------------ */ - -#define FMR3_CMI 0x08 -#define FMR3_SYNSA 0x04 -#define FMR3_CFRZ 0x02 -#define FMR3_EXTIW 0x01 - - - -/* CCB1-3 (Clear Channel Register) - ------------------- T1 ----------------------- */ - -#define CCB1_CH1 0x80 -#define CCB1_CH2 0x40 -#define CCB1_CH3 0x20 -#define CCB1_CH4 0x10 -#define CCB1_CH5 0x08 -#define CCB1_CH6 0x04 -#define CCB1_CH7 0x02 -#define CCB1_CH8 0x01 - -#define CCB2_CH9 0x80 -#define CCB2_CH10 0x40 -#define CCB2_CH11 0x20 -#define CCB2_CH12 0x10 -#define CCB2_CH13 0x08 -#define CCB2_CH14 0x04 -#define CCB2_CH15 0x02 -#define CCB2_CH16 0x01 - -#define CCB3_CH17 0x80 -#define CCB3_CH18 0x40 -#define CCB3_CH19 0x20 -#define CCB3_CH20 0x10 -#define CCB3_CH21 0x08 -#define CCB3_CH22 0x04 -#define CCB3_CH23 0x02 -#define CCB3_CH24 0x01 - - -/* LIM0/1 (Line Interface Mode 0/1) - ------------------- E1 & T1 --------------------------- */ - -#define LIM0_XFB 0x80 -#define LIM0_XDOS 0x40 -#define LIM0_SCL1 0x20 -#define LIM0_SCL0 0x10 -#define LIM0_EQON 0x08 -#define LIM0_ELOS 0x04 -#define LIM0_LL 0x02 -#define LIM0_MAS 0x01 - -#define LIM1_EFSC 0x80 -#define LIM1_RIL2 0x40 -#define LIM1_RIL1 0x20 -#define LIM1_RIL0 0x10 -#define LIM1_DCOC 0x08 -#define LIM1_JATT 0x04 -#define LIM1_RL 0x02 -#define LIM1_DRS 0x01 - - -/* PCDR (Pulse Count Detection Register(Read/Write)) - ------------------ E1 & T1 ------------------------- */ - -#define PCDR_PCD7 0x80 -#define PCDR_PCD6 0x40 -#define PCDR_PCD5 0x20 -#define PCDR_PCD4 0x10 -#define PCDR_PCD3 0x08 -#define PCDR_PCD2 0x04 -#define PCDR_PCD1 0x02 -#define PCDR_PCD0 0x01 - -#define PCRR_PCR7 0x80 -#define PCRR_PCR6 0x40 -#define PCRR_PCR5 0x20 -#define PCRR_PCR4 0x10 -#define PCRR_PCR3 0x08 -#define PCRR_PCR2 0x04 -#define PCRR_PCR1 0x02 -#define PCRR_PCR0 0x01 - - -/* LIM2 (Line Interface Mode 2) - - ------------------ E1 & T1 ---------------------------- */ - -#define LIM2_DJA2 0x20 -#define LIM2_DJA1 0x10 -#define LIM2_LOS2 0x02 -#define LIM2_LOS1 0x01 - -/* LCR1 (Loop Code Register 1) */ - -#define LCR1_EPRM 0x80 -#define LCR1_XPRBS 0x40 - -/* SIC1 (System Interface Control 1) */ -#define SIC1_SRSC 0x80 -#define SIC1_RBS1 0x20 -#define SIC1_RBS0 0x10 -#define SIC1_SXSC 0x08 -#define SIC1_XBS1 0x02 -#define SIC1_XBS0 0x01 - -/* DEC (Disable Error Counter) - ------------------ E1 & T1 ---------------------------- */ - -#define DEC_DCEC3 0x20 -#define DEC_DBEC 0x10 -#define DEC_DCEC1 0x08 -#define DEC_DCEC 0x08 -#define DEC_DEBC 0x04 -#define DEC_DCVC 0x02 -#define DEC_DFEC 0x01 - - -/* FALC Register Bits (Receive Mode) - ---------------------------------------------------------------------------- */ - - -/* FRS0/1 (Framer Receive Status Register 0/1) - ----------------- E1 & T1 ---------------------------------- */ - -#define FRS0_LOS 0x80 -#define FRS0_AIS 0x40 -#define FRS0_LFA 0x20 -#define FRS0_RRA 0x10 -#define FRS0_API 0x08 -#define FRS0_NMF 0x04 -#define FRS0_LMFA 0x02 -#define FRS0_FSRF 0x01 - -#define FRS1_TS16RA 0x40 -#define FRS1_TS16LOS 0x20 -#define FRS1_TS16AIS 0x10 -#define FRS1_TS16LFA 0x08 -#define FRS1_EXZD 0x80 -#define FRS1_LLBDD 0x10 -#define FRS1_LLBAD 0x08 -#define FRS1_XLS 0x02 -#define FRS1_XLO 0x01 -#define FRS1_PDEN 0x40 - -/* FRS2/3 (Framer Receive Status Register 2/3) - ----------------- T1 ---------------------------------- */ - -#define FRS2_ESC2 0x80 -#define FRS2_ESC1 0x40 -#define FRS2_ESC0 0x20 - -#define FRS3_FEH5 0x20 -#define FRS3_FEH4 0x10 -#define FRS3_FEH3 0x08 -#define FRS3_FEH2 0x04 -#define FRS3_FEH1 0x02 -#define FRS3_FEH0 0x01 - - -/* RSW (Receive Service Word Pulseframe) - ----------------- E1 ------------------------------ */ - -#define RSW_RSI 0x80 -#define RSW_RRA 0x20 -#define RSW_RYO 0x10 -#define RSW_RY1 0x08 -#define RSW_RY2 0x04 -#define RSW_RY3 0x02 -#define RSW_RY4 0x01 - - -/* RSP (Receive Spare Bits / Additional Status) - ---------------- E1 ------------------------------- */ - -#define RSP_SI1 0x80 -#define RSP_SI2 0x40 -#define RSP_LLBDD 0x10 -#define RSP_LLBAD 0x08 -#define RSP_RSIF 0x04 -#define RSP_RS13 0x02 -#define RSP_RS15 0x01 - - -/* FECL (Framing Error Counter) - ---------------- E1 & T1 -------------------------- */ - -#define FECL_FE7 0x80 -#define FECL_FE6 0x40 -#define FECL_FE5 0x20 -#define FECL_FE4 0x10 -#define FECL_FE3 0x08 -#define FECL_FE2 0x04 -#define FECL_FE1 0x02 -#define FECL_FE0 0x01 - -#define FECH_FE15 0x80 -#define FECH_FE14 0x40 -#define FECH_FE13 0x20 -#define FECH_FE12 0x10 -#define FECH_FE11 0x08 -#define FECH_FE10 0x04 -#define FECH_FE9 0x02 -#define FECH_FE8 0x01 - - -/* CVCl (Code Violation Counter) - ----------------- E1 ------------------------- */ - -#define CVCL_CV7 0x80 -#define CVCL_CV6 0x40 -#define CVCL_CV5 0x20 -#define CVCL_CV4 0x10 -#define CVCL_CV3 0x08 -#define CVCL_CV2 0x04 -#define CVCL_CV1 0x02 -#define CVCL_CV0 0x01 - -#define CVCH_CV15 0x80 -#define CVCH_CV14 0x40 -#define CVCH_CV13 0x20 -#define CVCH_CV12 0x10 -#define CVCH_CV11 0x08 -#define CVCH_CV10 0x04 -#define CVCH_CV9 0x02 -#define CVCH_CV8 0x01 - - -/* CEC1-3L (CRC Error Counter) - ------------------ E1 ----------------------------- */ - -#define CEC1L_CR7 0x80 -#define CEC1L_CR6 0x40 -#define CEC1L_CR5 0x20 -#define CEC1L_CR4 0x10 -#define CEC1L_CR3 0x08 -#define CEC1L_CR2 0x04 -#define CEC1L_CR1 0x02 -#define CEC1L_CR0 0x01 - -#define CEC1H_CR15 0x80 -#define CEC1H_CR14 0x40 -#define CEC1H_CR13 0x20 -#define CEC1H_CR12 0x10 -#define CEC1H_CR11 0x08 -#define CEC1H_CR10 0x04 -#define CEC1H_CR9 0x02 -#define CEC1H_CR8 0x01 - -#define CEC2L_CR7 0x80 -#define CEC2L_CR6 0x40 -#define CEC2L_CR5 0x20 -#define CEC2L_CR4 0x10 -#define CEC2L_CR3 0x08 -#define CEC2L_CR2 0x04 -#define CEC2L_CR1 0x02 -#define CEC2L_CR0 0x01 - -#define CEC2H_CR15 0x80 -#define CEC2H_CR14 0x40 -#define CEC2H_CR13 0x20 -#define CEC2H_CR12 0x10 -#define CEC2H_CR11 0x08 -#define CEC2H_CR10 0x04 -#define CEC2H_CR9 0x02 -#define CEC2H_CR8 0x01 - -#define CEC3L_CR7 0x80 -#define CEC3L_CR6 0x40 -#define CEC3L_CR5 0x20 -#define CEC3L_CR4 0x10 -#define CEC3L_CR3 0x08 -#define CEC3L_CR2 0x04 -#define CEC3L_CR1 0x02 -#define CEC3L_CR0 0x01 - -#define CEC3H_CR15 0x80 -#define CEC3H_CR14 0x40 -#define CEC3H_CR13 0x20 -#define CEC3H_CR12 0x10 -#define CEC3H_CR11 0x08 -#define CEC3H_CR10 0x04 -#define CEC3H_CR9 0x02 -#define CEC3H_CR8 0x01 - - -/* CECL (CRC Error Counter) - - ------------------ T1 ----------------------------- */ - -#define CECL_CR7 0x80 -#define CECL_CR6 0x40 -#define CECL_CR5 0x20 -#define CECL_CR4 0x10 -#define CECL_CR3 0x08 -#define CECL_CR2 0x04 -#define CECL_CR1 0x02 -#define CECL_CR0 0x01 - -#define CECH_CR15 0x80 -#define CECH_CR14 0x40 -#define CECH_CR13 0x20 -#define CECH_CR12 0x10 -#define CECH_CR11 0x08 -#define CECH_CR10 0x04 -#define CECH_CR9 0x02 -#define CECH_CR8 0x01 - -/* EBCL (E Bit Error Counter) - ------------------- E1 & T1 ------------------------- */ - -#define EBCL_EB7 0x80 -#define EBCL_EB6 0x40 -#define EBCL_EB5 0x20 -#define EBCL_EB4 0x10 -#define EBCL_EB3 0x08 -#define EBCL_EB2 0x04 -#define EBCL_EB1 0x02 -#define EBCL_EB0 0x01 - -#define EBCH_EB15 0x80 -#define EBCH_EB14 0x40 -#define EBCH_EB13 0x20 -#define EBCH_EB12 0x10 -#define EBCH_EB11 0x08 -#define EBCH_EB10 0x04 -#define EBCH_EB9 0x02 -#define EBCH_EB8 0x01 - - -/* RSA4-8 (Receive Sa4-8-Bit Register) - -------------------- E1 --------------------------- */ - -#define RSA4_RS47 0x80 -#define RSA4_RS46 0x40 -#define RSA4_RS45 0x20 -#define RSA4_RS44 0x10 -#define RSA4_RS43 0x08 -#define RSA4_RS42 0x04 -#define RSA4_RS41 0x02 -#define RSA4_RS40 0x01 - -#define RSA5_RS57 0x80 -#define RSA5_RS56 0x40 -#define RSA5_RS55 0x20 -#define RSA5_RS54 0x10 -#define RSA5_RS53 0x08 -#define RSA5_RS52 0x04 -#define RSA5_RS51 0x02 -#define RSA5_RS50 0x01 - -#define RSA6_RS67 0x80 -#define RSA6_RS66 0x40 -#define RSA6_RS65 0x20 -#define RSA6_RS64 0x10 -#define RSA6_RS63 0x08 -#define RSA6_RS62 0x04 -#define RSA6_RS61 0x02 -#define RSA6_RS60 0x01 - -#define RSA7_RS77 0x80 -#define RSA7_RS76 0x40 -#define RSA7_RS75 0x20 -#define RSA7_RS74 0x10 -#define RSA7_RS73 0x08 -#define RSA7_RS72 0x04 -#define RSA7_RS71 0x02 -#define RSA7_RS70 0x01 - -#define RSA8_RS87 0x80 -#define RSA8_RS86 0x40 -#define RSA8_RS85 0x20 -#define RSA8_RS84 0x10 -#define RSA8_RS83 0x08 -#define RSA8_RS82 0x04 -#define RSA8_RS81 0x02 -#define RSA8_RS80 0x01 - -/* RSA6S (Receive Sa6 Bit Status Register) - ------------------------ T1 ------------------------- */ - -#define RSA6S_SX 0x20 -#define RSA6S_SF 0x10 -#define RSA6S_SE 0x08 -#define RSA6S_SC 0x04 -#define RSA6S_SA 0x02 -#define RSA6S_S8 0x01 - - -/* RDL1-3 Receive DL-Bit Register1-3) - ------------------------ T1 ------------------------- */ - -#define RDL1_RDL17 0x80 -#define RDL1_RDL16 0x40 -#define RDL1_RDL15 0x20 -#define RDL1_RDL14 0x10 -#define RDL1_RDL13 0x08 -#define RDL1_RDL12 0x04 -#define RDL1_RDL11 0x02 -#define RDL1_RDL10 0x01 - -#define RDL2_RDL27 0x80 -#define RDL2_RDL26 0x40 -#define RDL2_RDL25 0x20 -#define RDL2_RDL24 0x10 -#define RDL2_RDL23 0x08 -#define RDL2_RDL22 0x04 -#define RDL2_RDL21 0x02 -#define RDL2_RDL20 0x01 - -#define RDL3_RDL37 0x80 -#define RDL3_RDL36 0x40 -#define RDL3_RDL35 0x20 -#define RDL3_RDL34 0x10 -#define RDL3_RDL33 0x08 -#define RDL3_RDL32 0x04 -#define RDL3_RDL31 0x02 -#define RDL3_RDL30 0x01 - - -/* SIS (Signaling Status Register) - - -------------------- E1 & T1 -------------------------- */ - -#define SIS_XDOV 0x80 -#define SIS_XFW 0x40 -#define SIS_XREP 0x20 -#define SIS_RLI 0x08 -#define SIS_CEC 0x04 -#define SIS_BOM 0x01 - - -/* RSIS (Receive Signaling Status Register) - - -------------------- E1 & T1 --------------------------- */ - -#define RSIS_VFR 0x80 -#define RSIS_RDO 0x40 -#define RSIS_CRC16 0x20 -#define RSIS_RAB 0x10 -#define RSIS_HA1 0x08 -#define RSIS_HA0 0x04 -#define RSIS_HFR 0x02 -#define RSIS_LA 0x01 - - -/* RBCL/H (Receive Byte Count Low/High) - - ------------------- E1 & T1 ----------------------- */ - -#define RBCL_RBC7 0x80 -#define RBCL_RBC6 0x40 -#define RBCL_RBC5 0x20 -#define RBCL_RBC4 0x10 -#define RBCL_RBC3 0x08 -#define RBCL_RBC2 0x04 -#define RBCL_RBC1 0x02 -#define RBCL_RBC0 0x01 - -#define RBCH_OV 0x10 -#define RBCH_RBC11 0x08 -#define RBCH_RBC10 0x04 -#define RBCH_RBC9 0x02 -#define RBCH_RBC8 0x01 - - -/* ISR1-3 (Interrupt Status Register 1-3) - - ------------------ E1 & T1 ------------------------------ */ - -#define FISR0_RME 0x80 -#define FISR0_RFS 0x40 -#define FISR0_T8MS 0x20 -#define FISR0_ISF 0x20 -#define FISR0_RMB 0x10 -#define FISR0_CASC 0x08 -#define FISR0_RSC 0x08 -#define FISR0_CRC6 0x04 -#define FISR0_CRC4 0x04 -#define FISR0_PDEN 0x02 -#define FISR0_RPF 0x01 - -#define FISR1_CASE 0x80 -#define FISR1_LLBSC 0x80 -#define FISR1_RDO 0x40 -#define FISR1_ALLS 0x20 -#define FISR1_XDU 0x10 -#define FISR1_XMB 0x08 -#define FISR1_XLSC 0x02 -#define FISR1_XPR 0x01 - -#define FISR2_FAR 0x80 -#define FISR2_LFA 0x40 -#define FISR2_MFAR 0x20 -#define FISR2_T400MS 0x10 -#define FISR2_LMFA 0x10 -#define FISR2_AIS 0x08 -#define FISR2_LOS 0x04 -#define FISR2_RAR 0x02 -#define FISR2_RA 0x01 - -#define FISR3_ES 0x80 -#define FISR3_SEC 0x40 -#define FISR3_LMFA16 0x20 -#define FISR3_AIS16 0x10 -#define FISR3_RA16 0x08 -#define FISR3_API 0x04 -#define FISR3_XSLP 0x20 -#define FISR3_XSLN 0x10 -#define FISR3_LLBSC 0x08 -#define FISR3_XRS 0x04 -#define FISR3_SLN 0x02 -#define FISR3_SLP 0x01 - - -/* GIS (Global Interrupt Status Register) - - --------------------- E1 & T1 --------------------- */ - -#define GIS_ISR3 0x08 -#define GIS_ISR2 0x04 -#define GIS_ISR1 0x02 -#define GIS_ISR0 0x01 - - -/* VSTR (Version Status Register) - - --------------------- E1 & T1 --------------------- */ - -#define VSTR_VN3 0x08 -#define VSTR_VN2 0x04 -#define VSTR_VN1 0x02 -#define VSTR_VN0 0x01 - - -/*>>>>>>>>>>>>>>>>>>>>> Local Control Structures <<<<<<<<<<<<<<<<<<<<<<<<< */ - -/* Write-only Registers (E1/T1 control mode write registers) */ -#define XFIFOH 0x00 /* Tx FIFO High Byte */ -#define XFIFOL 0x01 /* Tx FIFO Low Byte */ -#define CMDR 0x02 /* Command Reg */ -#define DEC 0x60 /* Disable Error Counter */ -#define TEST2 0x62 /* Manuf. Test Reg 2 */ -#define XS(nbr) (0x70 + (nbr)) /* Tx CAS Reg (0 to 15) */ - -/* Read-write Registers (E1/T1 status mode read registers) */ -#define MODE 0x03 /* Mode Reg */ -#define RAH1 0x04 /* Receive Address High 1 */ -#define RAH2 0x05 /* Receive Address High 2 */ -#define RAL1 0x06 /* Receive Address Low 1 */ -#define RAL2 0x07 /* Receive Address Low 2 */ -#define IPC 0x08 /* Interrupt Port Configuration */ -#define CCR1 0x09 /* Common Configuration Reg 1 */ -#define CCR3 0x0A /* Common Configuration Reg 3 */ -#define PRE 0x0B /* Preamble Reg */ -#define RTR1 0x0C /* Receive Timeslot Reg 1 */ -#define RTR2 0x0D /* Receive Timeslot Reg 2 */ -#define RTR3 0x0E /* Receive Timeslot Reg 3 */ -#define RTR4 0x0F /* Receive Timeslot Reg 4 */ -#define TTR1 0x10 /* Transmit Timeslot Reg 1 */ -#define TTR2 0x11 /* Transmit Timeslot Reg 2 */ -#define TTR3 0x12 /* Transmit Timeslot Reg 3 */ -#define TTR4 0x13 /* Transmit Timeslot Reg 4 */ -#define IMR0 0x14 /* Interrupt Mask Reg 0 */ -#define IMR1 0x15 /* Interrupt Mask Reg 1 */ -#define IMR2 0x16 /* Interrupt Mask Reg 2 */ -#define IMR3 0x17 /* Interrupt Mask Reg 3 */ -#define IMR4 0x18 /* Interrupt Mask Reg 4 */ -#define IMR5 0x19 /* Interrupt Mask Reg 5 */ -#define FMR0 0x1A /* Framer Mode Reigster 0 */ -#define FMR1 0x1B /* Framer Mode Reigster 1 */ -#define FMR2 0x1C /* Framer Mode Reigster 2 */ -#define LOOP 0x1D /* Channel Loop Back */ -#define XSW 0x1E /* Transmit Service Word */ -#define FMR4 0x1E /* Framer Mode Reg 4 */ -#define XSP 0x1F /* Transmit Spare Bits */ -#define FMR5 0x1F /* Framer Mode Reg 5 */ -#define XC0 0x20 /* Transmit Control 0 */ -#define XC1 0x21 /* Transmit Control 1 */ -#define RC0 0x22 /* Receive Control 0 */ -#define RC1 0x23 /* Receive Control 1 */ -#define XPM0 0x24 /* Transmit Pulse Mask 0 */ -#define XPM1 0x25 /* Transmit Pulse Mask 1 */ -#define XPM2 0x26 /* Transmit Pulse Mask 2 */ -#define TSWM 0x27 /* Transparent Service Word Mask */ -#define TEST1 0x28 /* Manuf. Test Reg 1 */ -#define IDLE 0x29 /* Idle Channel Code */ -#define XSA4 0x2A /* Transmit SA4 Bit Reg */ -#define XDL1 0x2A /* Transmit DL-Bit Reg 2 */ -#define XSA5 0x2B /* Transmit SA4 Bit Reg */ -#define XDL2 0x2B /* Transmit DL-Bit Reg 2 */ -#define XSA6 0x2C /* Transmit SA4 Bit Reg */ -#define XDL3 0x2C /* Transmit DL-Bit Reg 2 */ -#define XSA7 0x2D /* Transmit SA4 Bit Reg */ -#define CCB1 0x2D /* Clear Channel Reg 1 */ -#define XSA8 0x2E /* Transmit SA4 Bit Reg */ -#define CCB2 0x2E /* Clear Channel Reg 2 */ -#define FMR3 0x2F /* Framer Mode Reg. 3 */ -#define CCB3 0x2F /* Clear Channel Reg 3 */ -#define ICB1 0x30 /* Idle Channel Reg 1 */ -#define ICB2 0x31 /* Idle Channel Reg 2 */ -#define ICB3 0x32 /* Idle Channel Reg 3 */ -#define ICB4 0x33 /* Idle Channel Reg 4 */ -#define LIM0 0x34 /* Line Interface Mode 0 */ -#define LIM1 0x35 /* Line Interface Mode 1 */ -#define PCDR 0x36 /* Pulse Count Detection */ -#define PCRR 0x37 /* Pulse Count Recovery */ -#define LIM2 0x38 /* Line Interface Mode Reg 2 */ -#define LCR1 0x39 /* Loop Code Reg 1 */ -#define LCR2 0x3A /* Loop Code Reg 2 */ -#define LCR3 0x3B /* Loop Code Reg 3 */ -#define SIC1 0x3C /* System Interface Control 1 */ - -/* Read-only Registers (E1/T1 control mode read registers) */ -#define RFIFOH 0x00 /* Receive FIFO */ -#define RFIFOL 0x01 /* Receive FIFO */ -#define FRS0 0x4C /* Framer Receive Status 0 */ -#define FRS1 0x4D /* Framer Receive Status 1 */ -#define RSW 0x4E /* Receive Service Word */ -#define FRS2 0x4E /* Framer Receive Status 2 */ -#define RSP 0x4F /* Receive Spare Bits */ -#define FRS3 0x4F /* Framer Receive Status 3 */ -#define FECL 0x50 /* Framing Error Counter */ -#define FECH 0x51 /* Framing Error Counter */ -#define CVCL 0x52 /* Code Violation Counter */ -#define CVCH 0x53 /* Code Violation Counter */ -#define CECL 0x54 /* CRC Error Counter 1 */ -#define CECH 0x55 /* CRC Error Counter 1 */ -#define EBCL 0x56 /* E-Bit Error Counter */ -#define EBCH 0x57 /* E-Bit Error Counter */ -#define BECL 0x58 /* Bit Error Counter Low */ -#define BECH 0x59 /* Bit Error Counter Low */ -#define CEC3 0x5A /* CRC Error Counter 3 (16-bit) */ -#define RSA4 0x5C /* Receive SA4 Bit Reg */ -#define RDL1 0x5C /* Receive DL-Bit Reg 1 */ -#define RSA5 0x5D /* Receive SA5 Bit Reg */ -#define RDL2 0x5D /* Receive DL-Bit Reg 2 */ -#define RSA6 0x5E /* Receive SA6 Bit Reg */ -#define RDL3 0x5E /* Receive DL-Bit Reg 3 */ -#define RSA7 0x5F /* Receive SA7 Bit Reg */ -#define RSA8 0x60 /* Receive SA8 Bit Reg */ -#define RSA6S 0x61 /* Receive SA6 Bit Status Reg */ -#define TSR0 0x62 /* Manuf. Test Reg 0 */ -#define TSR1 0x63 /* Manuf. Test Reg 1 */ -#define SIS 0x64 /* Signaling Status Reg */ -#define RSIS 0x65 /* Receive Signaling Status Reg */ -#define RBCL 0x66 /* Receive Byte Control */ -#define RBCH 0x67 /* Receive Byte Control */ -#define FISR0 0x68 /* Interrupt Status Reg 0 */ -#define FISR1 0x69 /* Interrupt Status Reg 1 */ -#define FISR2 0x6A /* Interrupt Status Reg 2 */ -#define FISR3 0x6B /* Interrupt Status Reg 3 */ -#define GIS 0x6E /* Global Interrupt Status */ -#define VSTR 0x6F /* Version Status */ -#define RS(nbr) (0x70 + (nbr)) /* Rx CAS Reg (0 to 15) */ - -#endif /* _FALC_LH_H */ - diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h deleted file mode 100644 index 63e9fcf31fb..00000000000 --- a/drivers/net/wan/pc300.h +++ /dev/null @@ -1,482 +0,0 @@ -/* - * pc300.h Cyclades-PC300(tm) Kernel API Definitions. - * - * Author: Ivan Passos <ivan@cyclades.com> - * - * Copyright: (c) 1999-2002 Cyclades Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * $Log: pc300.h,v $ - * Revision 3.12 2002/03/07 14:17:09 henrique - * License data fixed - * - * Revision 3.11 2002/01/28 21:09:39 daniela - * Included ';' after pc300hw.bus. - * - * Revision 3.10 2002/01/17 17:58:52 ivan - * Support for PC300-TE/M (PMC). - * - * Revision 3.9 2001/09/28 13:30:53 daniela - * Renamed dma_start routine to rx_dma_start. - * - * Revision 3.8 2001/09/24 13:03:45 daniela - * Fixed BOF interrupt treatment. Created dma_start routine. - * - * Revision 3.7 2001/08/10 17:19:58 daniela - * Fixed IOCTLs defines. - * - * Revision 3.6 2001/07/18 19:24:42 daniela - * Included kernel version. - * - * Revision 3.5 2001/07/05 18:38:08 daniela - * DMA transmission bug fix. - * - * Revision 3.4 2001/06/26 17:10:40 daniela - * New configuration parameters (line code, CRC calculation and clock). - * - * Revision 3.3 2001/06/22 13:13:02 regina - * MLPPP implementation - * - * Revision 3.2 2001/06/18 17:56:09 daniela - * Increased DEF_MTU and TX_QUEUE_LEN. - * - * Revision 3.1 2001/06/15 12:41:10 regina - * upping major version number - * - * Revision 1.1.1.1 2001/06/13 20:25:06 daniela - * PC300 initial CVS version (3.4.0-pre1) - * - * Revision 2.3 2001/03/05 daniela - * Created struct pc300conf, to provide the hardware information to pc300util. - * Inclusion of 'alloc_ramsize' field on structure 'pc300hw'. - * - * Revision 2.2 2000/12/22 daniela - * Structures and defines to support pc300util: statistics, status, - * loopback tests, trace. - * - * Revision 2.1 2000/09/28 ivan - * Inclusion of 'iophys' and 'iosize' fields on structure 'pc300hw', to - * allow release of I/O region at module unload. - * Changed location of include files. - * - * Revision 2.0 2000/03/27 ivan - * Added support for the PC300/TE cards. - * - * Revision 1.1 2000/01/31 ivan - * Replaced 'pc300[drv|sca].h' former PC300 driver include files. - * - * Revision 1.0 1999/12/16 ivan - * First official release. - * Inclusion of 'nchan' field on structure 'pc300hw', to allow variable - * number of ports per card. - * Inclusion of 'if_ptr' field on structure 'pc300dev'. - * - * Revision 0.6 1999/11/17 ivan - * Changed X.25-specific function names to comply with adopted convention. - * - * Revision 0.5 1999/11/16 Daniela Squassoni - * X.25 support. - * - * Revision 0.4 1999/11/15 ivan - * Inclusion of 'clock' field on structure 'pc300hw'. - * - * Revision 0.3 1999/11/10 ivan - * IOCTL name changing. - * Inclusion of driver function prototypes. - * - * Revision 0.2 1999/11/03 ivan - * Inclusion of 'tx_skb' and union 'ifu' on structure 'pc300dev'. - * - * Revision 0.1 1999/01/15 ivan - * Initial version. - * - */ - -#ifndef _PC300_H -#define _PC300_H - -#include <linux/hdlc.h> -#include <net/syncppp.h> -#include "hd64572.h" -#include "pc300-falc-lh.h" - -#ifndef CY_TYPES -#define CY_TYPES -typedef __u64 ucdouble; /* 64 bits, unsigned */ -typedef __u32 uclong; /* 32 bits, unsigned */ -typedef __u16 ucshort; /* 16 bits, unsigned */ -typedef __u8 ucchar; /* 8 bits, unsigned */ -#endif /* CY_TYPES */ - -#define PC300_PROTO_MLPPP 1 - -#define PC300_KERNEL "2.4.x" /* Kernel supported by this driver */ - -#define PC300_DEVNAME "hdlc" /* Dev. name base (for hdlc0, hdlc1, etc.) */ -#define PC300_MAXINDEX 100 /* Max dev. name index (the '0' in hdlc0) */ - -#define PC300_MAXCARDS 4 /* Max number of cards per system */ -#define PC300_MAXCHAN 2 /* Number of channels per card */ - -#define PC300_PLX_WIN 0x80 /* PLX control window size (128b) */ -#define PC300_RAMSIZE 0x40000 /* RAM window size (256Kb) */ -#define PC300_SCASIZE 0x400 /* SCA window size (1Kb) */ -#define PC300_FALCSIZE 0x400 /* FALC window size (1Kb) */ - -#define PC300_OSC_CLOCK 24576000 -#define PC300_PCI_CLOCK 33000000 - -#define BD_DEF_LEN 0x0800 /* DMA buffer length (2KB) */ -#define DMA_TX_MEMSZ 0x8000 /* Total DMA Tx memory size (32KB/ch) */ -#define DMA_RX_MEMSZ 0x10000 /* Total DMA Rx memory size (64KB/ch) */ - -#define N_DMA_TX_BUF (DMA_TX_MEMSZ / BD_DEF_LEN) /* DMA Tx buffers */ -#define N_DMA_RX_BUF (DMA_RX_MEMSZ / BD_DEF_LEN) /* DMA Rx buffers */ - -/* DMA Buffer Offsets */ -#define DMA_TX_BASE ((N_DMA_TX_BUF + N_DMA_RX_BUF) * \ - PC300_MAXCHAN * sizeof(pcsca_bd_t)) -#define DMA_RX_BASE (DMA_TX_BASE + PC300_MAXCHAN*DMA_TX_MEMSZ) - -/* DMA Descriptor Offsets */ -#define DMA_TX_BD_BASE 0x0000 -#define DMA_RX_BD_BASE (DMA_TX_BD_BASE + ((PC300_MAXCHAN*DMA_TX_MEMSZ / \ - BD_DEF_LEN) * sizeof(pcsca_bd_t))) - -/* DMA Descriptor Macros */ -#define TX_BD_ADDR(chan, n) (DMA_TX_BD_BASE + \ - ((N_DMA_TX_BUF*chan) + n) * sizeof(pcsca_bd_t)) -#define RX_BD_ADDR(chan, n) (DMA_RX_BD_BASE + \ - ((N_DMA_RX_BUF*chan) + n) * sizeof(pcsca_bd_t)) - -/* Macro to access the FALC registers (TE only) */ -#define F_REG(reg, chan) (0x200*(chan) + ((reg)<<2)) - -/*************************************** - * Memory access functions/macros * - * (required to support Alpha systems) * - ***************************************/ -#ifdef __KERNEL__ -#define cpc_writeb(port,val) {writeb((ucchar)(val),(port)); mb();} -#define cpc_writew(port,val) {writew((ushort)(val),(port)); mb();} -#define cpc_writel(port,val) {writel((uclong)(val),(port)); mb();} - -#define cpc_readb(port) readb(port) -#define cpc_readw(port) readw(port) -#define cpc_readl(port) readl(port) - -#else /* __KERNEL__ */ -#define cpc_writeb(port,val) (*(volatile ucchar *)(port) = (ucchar)(val)) -#define cpc_writew(port,val) (*(volatile ucshort *)(port) = (ucshort)(val)) -#define cpc_writel(port,val) (*(volatile uclong *)(port) = (uclong)(val)) - -#define cpc_readb(port) (*(volatile ucchar *)(port)) -#define cpc_readw(port) (*(volatile ucshort *)(port)) -#define cpc_readl(port) (*(volatile uclong *)(port)) - -#endif /* __KERNEL__ */ - -/****** Data Structures *****************************************************/ - -/* - * RUNTIME_9050 - PLX PCI9050-1 local configuration and shared runtime - * registers. This structure can be used to access the 9050 registers - * (memory mapped). - */ -struct RUNTIME_9050 { - uclong loc_addr_range[4]; /* 00-0Ch : Local Address Ranges */ - uclong loc_rom_range; /* 10h : Local ROM Range */ - uclong loc_addr_base[4]; /* 14-20h : Local Address Base Addrs */ - uclong loc_rom_base; /* 24h : Local ROM Base */ - uclong loc_bus_descr[4]; /* 28-34h : Local Bus Descriptors */ - uclong rom_bus_descr; /* 38h : ROM Bus Descriptor */ - uclong cs_base[4]; /* 3C-48h : Chip Select Base Addrs */ - uclong intr_ctrl_stat; /* 4Ch : Interrupt Control/Status */ - uclong init_ctrl; /* 50h : EEPROM ctrl, Init Ctrl, etc */ -}; - -#define PLX_9050_LINT1_ENABLE 0x01 -#define PLX_9050_LINT1_POL 0x02 -#define PLX_9050_LINT1_STATUS 0x04 -#define PLX_9050_LINT2_ENABLE 0x08 -#define PLX_9050_LINT2_POL 0x10 -#define PLX_9050_LINT2_STATUS 0x20 -#define PLX_9050_INTR_ENABLE 0x40 -#define PLX_9050_SW_INTR 0x80 - -/* Masks to access the init_ctrl PLX register */ -#define PC300_CLKSEL_MASK (0x00000004UL) -#define PC300_CHMEDIA_MASK(chan) (0x00000020UL<<(chan*3)) -#define PC300_CTYPE_MASK (0x00000800UL) - -/* CPLD Registers (base addr = falcbase, TE only) */ -/* CPLD v. 0 */ -#define CPLD_REG1 0x140 /* Chip resets, DCD/CTS status */ -#define CPLD_REG2 0x144 /* Clock enable , LED control */ -/* CPLD v. 2 or higher */ -#define CPLD_V2_REG1 0x100 /* Chip resets, DCD/CTS status */ -#define CPLD_V2_REG2 0x104 /* Clock enable , LED control */ -#define CPLD_ID_REG 0x108 /* CPLD version */ - -/* CPLD Register bit description: for the FALC bits, they should always be - set based on the channel (use (bit<<(2*ch)) to access the correct bit for - that channel) */ -#define CPLD_REG1_FALC_RESET 0x01 -#define CPLD_REG1_SCA_RESET 0x02 -#define CPLD_REG1_GLOBAL_CLK 0x08 -#define CPLD_REG1_FALC_DCD 0x10 -#define CPLD_REG1_FALC_CTS 0x20 - -#define CPLD_REG2_FALC_TX_CLK 0x01 -#define CPLD_REG2_FALC_RX_CLK 0x02 -#define CPLD_REG2_FALC_LED1 0x10 -#define CPLD_REG2_FALC_LED2 0x20 - -/* Structure with FALC-related fields (TE only) */ -#define PC300_FALC_MAXLOOP 0x0000ffff /* for falc_issue_cmd() */ - -typedef struct falc { - ucchar sync; /* If true FALC is synchronized */ - ucchar active; /* if TRUE then already active */ - ucchar loop_active; /* if TRUE a line loopback UP was received */ - ucchar loop_gen; /* if TRUE a line loopback UP was issued */ - - ucchar num_channels; - ucchar offset; /* 1 for T1, 0 for E1 */ - ucchar full_bandwidth; - - ucchar xmb_cause; - ucchar multiframe_mode; - - /* Statistics */ - ucshort pden; /* Pulse Density violation count */ - ucshort los; /* Loss of Signal count */ - ucshort losr; /* Loss of Signal recovery count */ - ucshort lfa; /* Loss of frame alignment count */ - ucshort farec; /* Frame Alignment Recovery count */ - ucshort lmfa; /* Loss of multiframe alignment count */ - ucshort ais; /* Remote Alarm indication Signal count */ - ucshort sec; /* One-second timer */ - ucshort es; /* Errored second */ - ucshort rai; /* remote alarm received */ - ucshort bec; - ucshort fec; - ucshort cvc; - ucshort cec; - ucshort ebc; - - /* Status */ - ucchar red_alarm; - ucchar blue_alarm; - ucchar loss_fa; - ucchar yellow_alarm; - ucchar loss_mfa; - ucchar prbs; -} falc_t; - -typedef struct falc_status { - ucchar sync; /* If true FALC is synchronized */ - ucchar red_alarm; - ucchar blue_alarm; - ucchar loss_fa; - ucchar yellow_alarm; - ucchar loss_mfa; - ucchar prbs; -} falc_status_t; - -typedef struct rsv_x21_status { - ucchar dcd; - ucchar dsr; - ucchar cts; - ucchar rts; - ucchar dtr; -} rsv_x21_status_t; - -typedef struct pc300stats { - int hw_type; - uclong line_on; - uclong line_off; - struct net_device_stats gen_stats; - falc_t te_stats; -} pc300stats_t; - -typedef struct pc300status { - int hw_type; - rsv_x21_status_t gen_status; - falc_status_t te_status; -} pc300status_t; - -typedef struct pc300loopback { - char loop_type; - char loop_on; -} pc300loopback_t; - -typedef struct pc300patterntst { - char patrntst_on; /* 0 - off; 1 - on; 2 - read num_errors */ - ucshort num_errors; -} pc300patterntst_t; - -typedef struct pc300dev { - void *if_ptr; /* General purpose pointer */ - struct pc300ch *chan; - ucchar trace_on; - uclong line_on; /* DCD(X.21, RSV) / sync(TE) change counters */ - uclong line_off; -#ifdef __KERNEL__ - char name[16]; - struct net_device *dev; - - void *private; - struct sk_buff *tx_skb; - union { /* This union has all the protocol-specific structures */ - struct ppp_device pppdev; - }ifu; -#ifdef CONFIG_PC300_MLPPP - void *cpc_tty; /* information to PC300 TTY driver */ -#endif -#endif /* __KERNEL__ */ -}pc300dev_t; - -typedef struct pc300hw { - int type; /* RSV, X21, etc. */ - int bus; /* Bus (PCI, PMC, etc.) */ - int nchan; /* number of channels */ - int irq; /* interrupt request level */ - uclong clock; /* Board clock */ - ucchar cpld_id; /* CPLD ID (TE only) */ - ucshort cpld_reg1; /* CPLD reg 1 (TE only) */ - ucshort cpld_reg2; /* CPLD reg 2 (TE only) */ - ucshort gpioc_reg; /* PLX GPIOC reg */ - ucshort intctl_reg; /* PLX Int Ctrl/Status reg */ - uclong iophys; /* PLX registers I/O base */ - uclong iosize; /* PLX registers I/O size */ - uclong plxphys; /* PLX registers MMIO base (physical) */ - void __iomem * plxbase; /* PLX registers MMIO base (virtual) */ - uclong plxsize; /* PLX registers MMIO size */ - uclong scaphys; /* SCA registers MMIO base (physical) */ - void __iomem * scabase; /* SCA registers MMIO base (virtual) */ - uclong scasize; /* SCA registers MMIO size */ - uclong ramphys; /* On-board RAM MMIO base (physical) */ - void __iomem * rambase; /* On-board RAM MMIO base (virtual) */ - uclong alloc_ramsize; /* RAM MMIO size allocated by the PCI bridge */ - uclong ramsize; /* On-board RAM MMIO size */ - uclong falcphys; /* FALC registers MMIO base (physical) */ - void __iomem * falcbase;/* FALC registers MMIO base (virtual) */ - uclong falcsize; /* FALC registers MMIO size */ -} pc300hw_t; - -typedef struct pc300chconf { - sync_serial_settings phys_settings; /* Clock type/rate (in bps), - loopback mode */ - raw_hdlc_proto proto_settings; /* Encoding, parity (CRC) */ - uclong media; /* HW media (RS232, V.35, etc.) */ - uclong proto; /* Protocol (PPP, X.25, etc.) */ - ucchar monitor; /* Monitor mode (0 = off, !0 = on) */ - - /* TE-specific parameters */ - ucchar lcode; /* Line Code (AMI, B8ZS, etc.) */ - ucchar fr_mode; /* Frame Mode (ESF, D4, etc.) */ - ucchar lbo; /* Line Build Out */ - ucchar rx_sens; /* Rx Sensitivity (long- or short-haul) */ - uclong tslot_bitmap; /* bit[i]=1 => timeslot _i_ is active */ -} pc300chconf_t; - -typedef struct pc300ch { - struct pc300 *card; - int channel; - pc300dev_t d; - pc300chconf_t conf; - ucchar tx_first_bd; /* First TX DMA block descr. w/ data */ - ucchar tx_next_bd; /* Next free TX DMA block descriptor */ - ucchar rx_first_bd; /* First free RX DMA block descriptor */ - ucchar rx_last_bd; /* Last free RX DMA block descriptor */ - ucchar nfree_tx_bd; /* Number of free TX DMA block descriptors */ - falc_t falc; /* FALC structure (TE only) */ -} pc300ch_t; - -typedef struct pc300 { - pc300hw_t hw; /* hardware config. */ - pc300ch_t chan[PC300_MAXCHAN]; -#ifdef __KERNEL__ - spinlock_t card_lock; -#endif /* __KERNEL__ */ -} pc300_t; - -typedef struct pc300conf { - pc300hw_t hw; - pc300chconf_t conf; -} pc300conf_t; - -/* DEV ioctl() commands */ -#define N_SPPP_IOCTLS 2 - -enum pc300_ioctl_cmds { - SIOCCPCRESERVED = (SIOCDEVPRIVATE + N_SPPP_IOCTLS), - SIOCGPC300CONF, - SIOCSPC300CONF, - SIOCGPC300STATUS, - SIOCGPC300FALCSTATUS, - SIOCGPC300UTILSTATS, - SIOCGPC300UTILSTATUS, - SIOCSPC300TRACE, - SIOCSPC300LOOPBACK, - SIOCSPC300PATTERNTEST, -}; - -/* Loopback types - PC300/TE boards */ -enum pc300_loopback_cmds { - PC300LOCLOOP = 1, - PC300REMLOOP, - PC300PAYLOADLOOP, - PC300GENLOOPUP, - PC300GENLOOPDOWN, -}; - -/* Control Constant Definitions */ -#define PC300_RSV 0x01 -#define PC300_X21 0x02 -#define PC300_TE 0x03 - -#define PC300_PCI 0x00 -#define PC300_PMC 0x01 - -#define PC300_LC_AMI 0x01 -#define PC300_LC_B8ZS 0x02 -#define PC300_LC_NRZ 0x03 -#define PC300_LC_HDB3 0x04 - -/* Framing (T1) */ -#define PC300_FR_ESF 0x01 -#define PC300_FR_D4 0x02 -#define PC300_FR_ESF_JAPAN 0x03 - -/* Framing (E1) */ -#define PC300_FR_MF_CRC4 0x04 -#define PC300_FR_MF_NON_CRC4 0x05 -#define PC300_FR_UNFRAMED 0x06 - -#define PC300_LBO_0_DB 0x00 -#define PC300_LBO_7_5_DB 0x01 -#define PC300_LBO_15_DB 0x02 -#define PC300_LBO_22_5_DB 0x03 - -#define PC300_RX_SENS_SH 0x01 -#define PC300_RX_SENS_LH 0x02 - -#define PC300_TX_TIMEOUT (2*HZ) -#define PC300_TX_QUEUE_LEN 100 -#define PC300_DEF_MTU 1600 - -#ifdef __KERNEL__ -/* Function Prototypes */ -void tx_dma_start(pc300_t *, int); -int cpc_open(struct net_device *dev); -int cpc_set_media(hdlc_device *, int); -#endif /* __KERNEL__ */ - -#endif /* _PC300_H */ - diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c deleted file mode 100644 index 57914fbd41d..00000000000 --- a/drivers/net/wan/pc300_drv.c +++ /dev/null @@ -1,3706 +0,0 @@ -#define USE_PCI_CLOCK -static char rcsid[] = -"Revision: 3.4.5 Date: 2002/03/07 "; - -/* - * pc300.c Cyclades-PC300(tm) Driver. - * - * Author: Ivan Passos <ivan@cyclades.com> - * Maintainer: PC300 Maintainer <pc300@cyclades.com> - * - * Copyright: (c) 1999-2003 Cyclades Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Using tabstop = 4. - * - * $Log: pc300_drv.c,v $ - * Revision 3.23 2002/03/20 13:58:40 henrique - * Fixed ortographic mistakes - * - * Revision 3.22 2002/03/13 16:56:56 henrique - * Take out the debug messages - * - * Revision 3.21 2002/03/07 14:17:09 henrique - * License data fixed - * - * Revision 3.20 2002/01/17 17:58:52 ivan - * Support for PC300-TE/M (PMC). - * - * Revision 3.19 2002/01/03 17:08:47 daniela - * Enables DMA reception when the SCA-II disables it improperly. - * - * Revision 3.18 2001/12/03 18:47:50 daniela - * Esthetic changes. - * - * Revision 3.17 2001/10/19 16:50:13 henrique - * Patch to kernel 2.4.12 and new generic hdlc. - * - * Revision 3.16 2001/10/16 15:12:31 regina - * clear statistics - * - * Revision 3.11 to 3.15 2001/10/11 20:26:04 daniela - * More DMA fixes for noisy lines. - * Return the size of bad frames in dma_get_rx_frame_size, so that the Rx buffer - * descriptors can be cleaned by dma_buf_read (called in cpc_net_rx). - * Renamed dma_start routine to rx_dma_start. Improved Rx statistics. - * Fixed BOF interrupt treatment. Created dma_start routine. - * Changed min and max to cpc_min and cpc_max. - * - * Revision 3.10 2001/08/06 12:01:51 regina - * Fixed problem in DSR_DE bit. - * - * Revision 3.9 2001/07/18 19:27:26 daniela - * Added some history comments. - * - * Revision 3.8 2001/07/12 13:11:19 regina - * bug fix - DCD-OFF in pc300 tty driver - * - * Revision 3.3 to 3.7 2001/07/06 15:00:20 daniela - * Removing kernel 2.4.3 and previous support. - * DMA transmission bug fix. - * MTU check in cpc_net_rx fixed. - * Boot messages reviewed. - * New configuration parameters (line code, CRC calculation and clock). - * - * Revision 3.2 2001/06/22 13:13:02 regina - * MLPPP implementation. Changed the header of message trace to include - * the device name. New format : "hdlcX[R/T]: ". - * Default configuration changed. - * - * Revision 3.1 2001/06/15 regina - * in cpc_queue_xmit, netif_stop_queue is called if don't have free descriptor - * upping major version number - * - * Revision 1.1.1.1 2001/06/13 20:25:04 daniela - * PC300 initial CVS version (3.4.0-pre1) - * - * Revision 3.0.1.2 2001/06/08 daniela - * Did some changes in the DMA programming implementation to avoid the - * occurrence of a SCA-II bug when CDA is accessed during a DMA transfer. - * - * Revision 3.0.1.1 2001/05/02 daniela - * Added kernel 2.4.3 support. - * - * Revision 3.0.1.0 2001/03/13 daniela, henrique - * Added Frame Relay Support. - * Driver now uses HDLC generic driver to provide protocol support. - * - * Revision 3.0.0.8 2001/03/02 daniela - * Fixed ram size detection. - * Changed SIOCGPC300CONF ioctl, to give hw information to pc300util. - * - * Revision 3.0.0.7 2001/02/23 daniela - * netif_stop_queue called before the SCA-II transmition commands in - * cpc_queue_xmit, and with interrupts disabled to avoid race conditions with - * transmition interrupts. - * Fixed falc_check_status for Unframed E1. - * - * Revision 3.0.0.6 2000/12/13 daniela - * Implemented pc300util support: trace, statistics, status and loopback - * tests for the PC300 TE boards. - * - * Revision 3.0.0.5 2000/12/12 ivan - * Added support for Unframed E1. - * Implemented monitor mode. - * Fixed DCD sensitivity on the second channel. - * Driver now complies with new PCI kernel architecture. - * - * Revision 3.0.0.4 2000/09/28 ivan - * Implemented DCD sensitivity. - * Moved hardware-specific open to the end of cpc_open, to avoid race - * conditions with early reception interrupts. - * Included code for [request|release]_mem_region(). - * Changed location of pc300.h . - * Minor code revision (contrib. of Jeff Garzik). - * - * Revision 3.0.0.3 2000/07/03 ivan - * Previous bugfix for the framing errors with external clock made X21 - * boards stop working. This version fixes it. - * - * Revision 3.0.0.2 2000/06/23 ivan - * Revisited cpc_queue_xmit to prevent race conditions on Tx DMA buffer - * handling when Tx timeouts occur. - * Revisited Rx statistics. - * Fixed a bug in the SCA-II programming that would cause framing errors - * when external clock was configured. - * - * Revision 3.0.0.1 2000/05/26 ivan - * Added logic in the SCA interrupt handler so that no board can monopolize - * the driver. - * Request PLX I/O region, although driver doesn't use it, to avoid - * problems with other drivers accessing it. - * - * Revision 3.0.0.0 2000/05/15 ivan - * Did some changes in the DMA programming implementation to avoid the - * occurrence of a SCA-II bug in the second channel. - * Implemented workaround for PLX9050 bug that would cause a system lockup - * in certain systems, depending on the MMIO addresses allocated to the - * board. - * Fixed the FALC chip programming to avoid synchronization problems in the - * second channel (TE only). - * Implemented a cleaner and faster Tx DMA descriptor cleanup procedure in - * cpc_queue_xmit(). - * Changed the built-in driver implementation so that the driver can use the - * general 'hdlcN' naming convention instead of proprietary device names. - * Driver load messages are now device-centric, instead of board-centric. - * Dynamic allocation of net_device structures. - * Code is now compliant with the new module interface (module_[init|exit]). - * Make use of the PCI helper functions to access PCI resources. - * - * Revision 2.0.0.0 2000/04/15 ivan - * Added support for the PC300/TE boards (T1/FT1/E1/FE1). - * - * Revision 1.1.0.0 2000/02/28 ivan - * Major changes in the driver architecture. - * Softnet compliancy implemented. - * Driver now reports physical instead of virtual memory addresses. - * Added cpc_change_mtu function. - * - * Revision 1.0.0.0 1999/12/16 ivan - * First official release. - * Support for 1- and 2-channel boards (which use distinct PCI Device ID's). - * Support for monolythic installation (i.e., drv built into the kernel). - * X.25 additional checking when lapb_[dis]connect_request returns an error. - * SCA programming now covers X.21 as well. - * - * Revision 0.3.1.0 1999/11/18 ivan - * Made X.25 support configuration-dependent (as it depends on external - * modules to work). - * Changed X.25-specific function names to comply with adopted convention. - * Fixed typos in X.25 functions that would cause compile errors (Daniela). - * Fixed bug in ch_config that would disable interrupts on a previously - * enabled channel if the other channel on the same board was enabled later. - * - * Revision 0.3.0.0 1999/11/16 daniela - * X.25 support. - * - * Revision 0.2.3.0 1999/11/15 ivan - * Function cpc_ch_status now provides more detailed information. - * Added support for X.21 clock configuration. - * Changed TNR1 setting in order to prevent Tx FIFO overaccesses by the SCA. - * Now using PCI clock instead of internal oscillator clock for the SCA. - * - * Revision 0.2.2.0 1999/11/10 ivan - * Changed the *_dma_buf_check functions so that they would print only - * the useful info instead of the whole buffer descriptor bank. - * Fixed bug in cpc_queue_xmit that would eventually crash the system - * in case of a packet drop. - * Implemented TX underrun handling. - * Improved SCA fine tuning to boost up its performance. - * - * Revision 0.2.1.0 1999/11/03 ivan - * Added functions *dma_buf_pt_init to allow independent initialization - * of the next-descr. and DMA buffer pointers on the DMA descriptors. - * Kernel buffer release and tbusy clearing is now done in the interrupt - * handler. - * Fixed bug in cpc_open that would cause an interface reopen to fail. - * Added a protocol-specific code section in cpc_net_rx. - * Removed printk level defs (they might be added back after the beta phase). - * - * Revision 0.2.0.0 1999/10/28 ivan - * Revisited the code so that new protocols can be easily added / supported. - * - * Revision 0.1.0.1 1999/10/20 ivan - * Mostly "esthetic" changes. - * - * Revision 0.1.0.0 1999/10/11 ivan - * Initial version. - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/net.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/netdevice.h> -#include <linux/spinlock.h> -#include <linux/if.h> - -#include <net/syncppp.h> -#include <net/arp.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - -#include "pc300.h" - -#define CPC_LOCK(card,flags) \ - do { \ - spin_lock_irqsave(&card->card_lock, flags); \ - } while (0) - -#define CPC_UNLOCK(card,flags) \ - do { \ - spin_unlock_irqrestore(&card->card_lock, flags); \ - } while (0) - -#undef PC300_DEBUG_PCI -#undef PC300_DEBUG_INTR -#undef PC300_DEBUG_TX -#undef PC300_DEBUG_RX -#undef PC300_DEBUG_OTHER - -static struct pci_device_id cpc_pci_dev_id[] __devinitdata = { - /* PC300/RSV or PC300/X21, 2 chan */ - {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300}, - /* PC300/RSV or PC300/X21, 1 chan */ - {0x120e, 0x301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x301}, - /* PC300/TE, 2 chan */ - {0x120e, 0x310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x310}, - /* PC300/TE, 1 chan */ - {0x120e, 0x311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x311}, - /* PC300/TE-M, 2 chan */ - {0x120e, 0x320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x320}, - /* PC300/TE-M, 1 chan */ - {0x120e, 0x321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x321}, - /* End of table */ - {0,}, -}; -MODULE_DEVICE_TABLE(pci, cpc_pci_dev_id); - -#ifndef cpc_min -#define cpc_min(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef cpc_max -#define cpc_max(a,b) (((a)>(b))?(a):(b)) -#endif - -/* prototypes */ -static void tx_dma_buf_pt_init(pc300_t *, int); -static void tx_dma_buf_init(pc300_t *, int); -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 *); -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 *); -static void plx_init(pc300_t *); -static void cpc_trace(struct net_device *, struct sk_buff *, char); -static int cpc_attach(struct net_device *, unsigned short, unsigned short); -static int cpc_close(struct net_device *dev); - -#ifdef CONFIG_PC300_MLPPP -void cpc_tty_init(pc300dev_t * dev); -void cpc_tty_unregister_service(pc300dev_t * pc300dev); -void cpc_tty_receive(pc300dev_t * pc300dev); -void cpc_tty_trigger_poll(pc300dev_t * pc300dev); -void cpc_tty_reset_var(void); -#endif - -/************************/ -/*** DMA Routines ***/ -/************************/ -static void tx_dma_buf_pt_init(pc300_t * card, int ch) -{ - int i; - int ch_factor = ch * N_DMA_TX_BUF; - volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase - + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); - - for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) { - cpc_writel(&ptdescr->next, (uclong) (DMA_TX_BD_BASE + - (ch_factor + ((i + 1) & (N_DMA_TX_BUF - 1))) * sizeof(pcsca_bd_t))); - cpc_writel(&ptdescr->ptbuf, - (uclong) (DMA_TX_BASE + (ch_factor + i) * BD_DEF_LEN)); - } -} - -static void tx_dma_buf_init(pc300_t * card, int ch) -{ - int i; - int ch_factor = ch * N_DMA_TX_BUF; - volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase - + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); - - for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) { - memset_io(ptdescr, 0, sizeof(pcsca_bd_t)); - cpc_writew(&ptdescr->len, 0); - cpc_writeb(&ptdescr->status, DST_OSB); - } - tx_dma_buf_pt_init(card, ch); -} - -static void rx_dma_buf_pt_init(pc300_t * card, int ch) -{ - int i; - int ch_factor = ch * N_DMA_RX_BUF; - volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase - + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); - - for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) { - cpc_writel(&ptdescr->next, (uclong) (DMA_RX_BD_BASE + - (ch_factor + ((i + 1) & (N_DMA_RX_BUF - 1))) * sizeof(pcsca_bd_t))); - cpc_writel(&ptdescr->ptbuf, - (uclong) (DMA_RX_BASE + (ch_factor + i) * BD_DEF_LEN)); - } -} - -static void rx_dma_buf_init(pc300_t * card, int ch) -{ - int i; - int ch_factor = ch * N_DMA_RX_BUF; - volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase - + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); - - for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) { - memset_io(ptdescr, 0, sizeof(pcsca_bd_t)); - cpc_writew(&ptdescr->len, 0); - cpc_writeb(&ptdescr->status, 0); - } - rx_dma_buf_pt_init(card, ch); -} - -static void tx_dma_buf_check(pc300_t * card, int ch) -{ - volatile pcsca_bd_t __iomem *ptdescr; - int i; - ucshort first_bd = card->chan[ch].tx_first_bd; - ucshort next_bd = card->chan[ch].tx_next_bd; - - printk("#CH%d: f_bd = %d(0x%08zx), n_bd = %d(0x%08zx)\n", ch, - first_bd, TX_BD_ADDR(ch, first_bd), - next_bd, TX_BD_ADDR(ch, next_bd)); - for (i = first_bd, - ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd)); - i != ((next_bd + 1) & (N_DMA_TX_BUF - 1)); - i = (i + 1) & (N_DMA_TX_BUF - 1), - ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) { - printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", - ch, i, cpc_readl(&ptdescr->next), - cpc_readl(&ptdescr->ptbuf), - cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); - } - printk("\n"); -} - -#ifdef PC300_DEBUG_OTHER -/* Show all TX buffer descriptors */ -static void tx1_dma_buf_check(pc300_t * card, int ch) -{ - volatile pcsca_bd_t __iomem *ptdescr; - int i; - ucshort first_bd = card->chan[ch].tx_first_bd; - ucshort next_bd = card->chan[ch].tx_next_bd; - uclong scabase = card->hw.scabase; - - printk ("\nnfree_tx_bd = %d \n", card->chan[ch].nfree_tx_bd); - printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, - first_bd, TX_BD_ADDR(ch, first_bd), - next_bd, TX_BD_ADDR(ch, next_bd)); - printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n", - cpc_readl(scabase + DTX_REG(CDAL, ch)), - cpc_readl(scabase + DTX_REG(EDAL, ch))); - for (i = 0; i < N_DMA_TX_BUF; i++) { - ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i)); - printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", - ch, i, cpc_readl(&ptdescr->next), - cpc_readl(&ptdescr->ptbuf), - cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); - } - printk("\n"); -} -#endif - -static void rx_dma_buf_check(pc300_t * card, int ch) -{ - volatile pcsca_bd_t __iomem *ptdescr; - int i; - ucshort first_bd = card->chan[ch].rx_first_bd; - ucshort last_bd = card->chan[ch].rx_last_bd; - int ch_factor; - - ch_factor = ch * N_DMA_RX_BUF; - printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd); - for (i = 0, ptdescr = (card->hw.rambase + - DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); - i < N_DMA_RX_BUF; i++, ptdescr++) { - if (cpc_readb(&ptdescr->status) & DST_OSB) - printk ("\n CH%d RX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", - ch, i, cpc_readl(&ptdescr->next), - cpc_readl(&ptdescr->ptbuf), - cpc_readb(&ptdescr->status), - cpc_readw(&ptdescr->len)); - } - printk("\n"); -} - -static int dma_get_rx_frame_size(pc300_t * card, int ch) -{ - volatile pcsca_bd_t __iomem *ptdescr; - ucshort first_bd = card->chan[ch].rx_first_bd; - int rcvd = 0; - volatile ucchar status; - - ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd)); - while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { - rcvd += cpc_readw(&ptdescr->len); - first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); - if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) { - /* Return the size of a good frame or incomplete bad frame - * (dma_buf_read will clean the buffer descriptors in this case). */ - return (rcvd); - } - ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); - } - return (-1); -} - -/* - * dma_buf_write: writes a frame to the Tx DMA buffers - * NOTE: this function writes one frame at a time. - */ -static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len) -{ - int i, nchar; - volatile pcsca_bd_t __iomem *ptdescr; - int tosend = len; - ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1; - - if (nbuf >= card->chan[ch].nfree_tx_bd) { - return -ENOMEM; - } - - for (i = 0; i < nbuf; i++) { - ptdescr = (card->hw.rambase + - TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); - nchar = cpc_min(BD_DEF_LEN, tosend); - if (cpc_readb(&ptdescr->status) & DST_OSB) { - memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), - &ptdata[len - tosend], nchar); - cpc_writew(&ptdescr->len, nchar); - card->chan[ch].nfree_tx_bd--; - if ((i + 1) == nbuf) { - /* This must be the last BD to be used */ - cpc_writeb(&ptdescr->status, DST_EOM); - } else { - cpc_writeb(&ptdescr->status, 0); - } - } else { - return -ENOMEM; - } - tosend -= nchar; - card->chan[ch].tx_next_bd = - (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1); - } - /* If it gets to here, it means we have sent the whole frame */ - return 0; -} - -/* - * dma_buf_read: reads a frame from the Rx DMA buffers - * NOTE: this function reads one frame at a time. - */ -static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) -{ - int nchar; - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - volatile pcsca_bd_t __iomem *ptdescr; - int rcvd = 0; - volatile ucchar status; - - ptdescr = (card->hw.rambase + - RX_BD_ADDR(ch, chan->rx_first_bd)); - while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { - nchar = cpc_readw(&ptdescr->len); - if ((status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) - || (nchar > BD_DEF_LEN)) { - - if (nchar > BD_DEF_LEN) - status |= DST_RBIT; - rcvd = -status; - /* Discard remaining descriptors used by the bad frame */ - while (chan->rx_first_bd != chan->rx_last_bd) { - cpc_writeb(&ptdescr->status, 0); - chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1); - if (status & DST_EOM) - break; - ptdescr = (card->hw.rambase + - cpc_readl(&ptdescr->next)); - status = cpc_readb(&ptdescr->status); - } - break; - } - if (nchar != 0) { - if (skb) { - memcpy_fromio(skb_put(skb, nchar), - (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar); - } - rcvd += nchar; - } - cpc_writeb(&ptdescr->status, 0); - cpc_writeb(&ptdescr->len, 0); - chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1); - - if (status & DST_EOM) - break; - - ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); - } - - if (rcvd != 0) { - /* Update pointer */ - chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1); - /* Update EDA */ - cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), - RX_BD_ADDR(ch, chan->rx_last_bd)); - } - return (rcvd); -} - -static void tx_dma_stop(pc300_t * card, int ch) -{ - void __iomem *scabase = card->hw.scabase; - ucchar drr_ena_bit = 1 << (5 + 2 * ch); - ucchar drr_rst_bit = 1 << (1 + 2 * ch); - - /* Disable DMA */ - cpc_writeb(scabase + DRR, drr_ena_bit); - cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); -} - -static void rx_dma_stop(pc300_t * card, int ch) -{ - void __iomem *scabase = card->hw.scabase; - ucchar drr_ena_bit = 1 << (4 + 2 * ch); - ucchar drr_rst_bit = 1 << (2 * ch); - - /* Disable DMA */ - cpc_writeb(scabase + DRR, drr_ena_bit); - cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); -} - -static void rx_dma_start(pc300_t * card, int ch) -{ - void __iomem *scabase = card->hw.scabase; - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - - /* Start DMA */ - cpc_writel(scabase + DRX_REG(CDAL, ch), - RX_BD_ADDR(ch, chan->rx_first_bd)); - if (cpc_readl(scabase + DRX_REG(CDAL,ch)) != - RX_BD_ADDR(ch, chan->rx_first_bd)) { - cpc_writel(scabase + DRX_REG(CDAL, ch), - RX_BD_ADDR(ch, chan->rx_first_bd)); - } - cpc_writel(scabase + DRX_REG(EDAL, ch), - RX_BD_ADDR(ch, chan->rx_last_bd)); - cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN); - cpc_writeb(scabase + DSR_RX(ch), DSR_DE); - if (!(cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { - cpc_writeb(scabase + DSR_RX(ch), DSR_DE); - } -} - -/*************************/ -/*** FALC Routines ***/ -/*************************/ -static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd) -{ - void __iomem *falcbase = card->hw.falcbase; - unsigned long i = 0; - - while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) { - if (i++ >= PC300_FALC_MAXLOOP) { - printk("%s: FALC command locked(cmd=0x%x).\n", - card->chan[ch].d.name, cmd); - break; - } - } - cpc_writeb(falcbase + F_REG(CMDR, ch), cmd); -} - -static void falc_intr_enable(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - /* Interrupt pins are open-drain */ - cpc_writeb(falcbase + F_REG(IPC, ch), - cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0); - /* Conters updated each second */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM); - /* Enable SEC and ES interrupts */ - cpc_writeb(falcbase + F_REG(IMR3, ch), - cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES)); - if (conf->fr_mode == PC300_FR_UNFRAMED) { - cpc_writeb(falcbase + F_REG(IMR4, ch), - cpc_readb(falcbase + F_REG(IMR4, ch)) & ~(IMR4_LOS)); - } else { - cpc_writeb(falcbase + F_REG(IMR4, ch), - cpc_readb(falcbase + F_REG(IMR4, ch)) & - ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP)); - } - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(IMR3, ch), - cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC); - } else { - cpc_writeb(falcbase + F_REG(IPC, ch), - cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI); - if (conf->fr_mode == PC300_FR_UNFRAMED) { - cpc_writeb(falcbase + F_REG(IMR2, ch), - cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_LOS)); - } else { - cpc_writeb(falcbase + F_REG(IMR2, ch), - cpc_readb(falcbase + F_REG(IMR2, ch)) & - ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS)); - if (pfalc->multiframe_mode) { - cpc_writeb(falcbase + F_REG(IMR2, ch), - cpc_readb(falcbase + F_REG(IMR2, ch)) & - ~(IMR2_T400MS | IMR2_MFAR)); - } else { - cpc_writeb(falcbase + F_REG(IMR2, ch), - cpc_readb(falcbase + F_REG(IMR2, ch)) | - IMR2_T400MS | IMR2_MFAR); - } - } - } -} - -static void falc_open_timeslot(pc300_t * card, int ch, int timeslot) -{ - void __iomem *falcbase = card->hw.falcbase; - ucchar tshf = card->chan[ch].falc.offset; - - cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), - cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) & - ~(0x80 >> ((timeslot - tshf) & 0x07))); - cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch), - cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) | - (0x80 >> (timeslot & 0x07))); - cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch), - cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) | - (0x80 >> (timeslot & 0x07))); -} - -static void falc_close_timeslot(pc300_t * card, int ch, int timeslot) -{ - void __iomem *falcbase = card->hw.falcbase; - ucchar tshf = card->chan[ch].falc.offset; - - cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), - cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) | - (0x80 >> ((timeslot - tshf) & 0x07))); - cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch), - cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) & - ~(0x80 >> (timeslot & 0x07))); - cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch), - cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) & - ~(0x80 >> (timeslot & 0x07))); -} - -static void falc_close_all_timeslots(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - void __iomem *falcbase = card->hw.falcbase; - - cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff); - cpc_writeb(falcbase + F_REG(TTR1, ch), 0); - cpc_writeb(falcbase + F_REG(RTR1, ch), 0); - cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff); - cpc_writeb(falcbase + F_REG(TTR2, ch), 0); - cpc_writeb(falcbase + F_REG(RTR2, ch), 0); - cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff); - cpc_writeb(falcbase + F_REG(TTR3, ch), 0); - cpc_writeb(falcbase + F_REG(RTR3, ch), 0); - if (conf->media == IF_IFACE_E1) { - cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); - cpc_writeb(falcbase + F_REG(TTR4, ch), 0); - cpc_writeb(falcbase + F_REG(RTR4, ch), 0); - } -} - -static void falc_open_all_timeslots(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - void __iomem *falcbase = card->hw.falcbase; - - cpc_writeb(falcbase + F_REG(ICB1, ch), 0); - if (conf->fr_mode == PC300_FR_UNFRAMED) { - cpc_writeb(falcbase + F_REG(TTR1, ch), 0xff); - cpc_writeb(falcbase + F_REG(RTR1, ch), 0xff); - } else { - /* Timeslot 0 is never enabled */ - cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f); - cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f); - } - cpc_writeb(falcbase + F_REG(ICB2, ch), 0); - cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff); - cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff); - cpc_writeb(falcbase + F_REG(ICB3, ch), 0); - cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff); - cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff); - if (conf->media == IF_IFACE_E1) { - cpc_writeb(falcbase + F_REG(ICB4, ch), 0); - cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff); - cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff); - } else { - cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); - cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80); - cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80); - } -} - -static void falc_init_timeslot(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - int tslot; - - for (tslot = 0; tslot < pfalc->num_channels; tslot++) { - if (conf->tslot_bitmap & (1 << tslot)) { - // Channel enabled - falc_open_timeslot(card, ch, tslot + 1); - } else { - // Channel disabled - falc_close_timeslot(card, ch, tslot + 1); - } - } -} - -static void falc_enable_comm(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - - if (pfalc->full_bandwidth) { - falc_open_all_timeslots(card, ch); - } else { - falc_init_timeslot(card, ch); - } - // CTS/DCD ON - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) & - ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch))); -} - -static void falc_disable_comm(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - - if (pfalc->loop_active != 2) { - falc_close_all_timeslots(card, ch); - } - // CTS/DCD OFF - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) | - ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch))); -} - -static void falc_init_t1(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); - - /* Switch to T1 mode (PCM 24) */ - cpc_writeb(falcbase + F_REG(FMR1, ch), FMR1_PMOD); - - /* Wait 20 us for setup */ - udelay(20); - - /* Transmit Buffer Size (1 frame) */ - cpc_writeb(falcbase + F_REG(SIC1, ch), SIC1_XBS0); - - /* Clock mode */ - if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */ - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); - } else { /* Slave mode */ - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); - cpc_writeb(falcbase + F_REG(LOOP, ch), - cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM); - } - - cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI); - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) & - ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1)); - - switch (conf->lcode) { - case PC300_LC_AMI: - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | - FMR0_XC1 | FMR0_RC1); - /* Clear Channel register to ON for all channels */ - cpc_writeb(falcbase + F_REG(CCB1, ch), 0xff); - cpc_writeb(falcbase + F_REG(CCB2, ch), 0xff); - cpc_writeb(falcbase + F_REG(CCB3, ch), 0xff); - break; - - case PC300_LC_B8ZS: - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | - FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1); - break; - - case PC300_LC_NRZ: - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | 0x00); - break; - } - - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_ELOS); - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0)); - /* Set interface mode to 2 MBPS */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); - - switch (conf->fr_mode) { - case PC300_FR_ESF: - pfalc->multiframe_mode = 0; - cpc_writeb(falcbase + F_REG(FMR4, ch), - cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_FM1); - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | - FMR1_CRC | FMR1_EDL); - cpc_writeb(falcbase + F_REG(XDL1, ch), 0); - cpc_writeb(falcbase + F_REG(XDL2, ch), 0); - cpc_writeb(falcbase + F_REG(XDL3, ch), 0); - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) & ~FMR0_SRAF); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2,ch)) | FMR2_MCSP | FMR2_SSP); - break; - - case PC300_FR_D4: - pfalc->multiframe_mode = 1; - cpc_writeb(falcbase + F_REG(FMR4, ch), - cpc_readb(falcbase + F_REG(FMR4, ch)) & - ~(FMR4_FM1 | FMR4_FM0)); - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | FMR0_SRAF); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_SSP); - break; - } - - /* Enable Automatic Resynchronization */ - cpc_writeb(falcbase + F_REG(FMR4, ch), - cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_AUTO); - - /* Transmit Automatic Remote Alarm */ - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA); - - /* Channel translation mode 1 : one to one */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_CTM); - - /* No signaling */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_SIGM); - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) & - ~(FMR5_EIBR | FMR5_SRS)); - cpc_writeb(falcbase + F_REG(CCR1, ch), 0); - - cpc_writeb(falcbase + F_REG(LIM1, ch), - cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); - - switch (conf->lbo) { - /* Provides proper Line Build Out */ - case PC300_LBO_0_DB: - cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja)); - cpc_writeb(falcbase + F_REG(XPM0, ch), 0x5a); - cpc_writeb(falcbase + F_REG(XPM1, ch), 0x8f); - cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); - break; - case PC300_LBO_7_5_DB: - cpc_writeb(falcbase + F_REG(LIM2, ch), (0x40 | LIM2_LOS1 | dja)); - cpc_writeb(falcbase + F_REG(XPM0, ch), 0x11); - cpc_writeb(falcbase + F_REG(XPM1, ch), 0x02); - cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); - break; - case PC300_LBO_15_DB: - cpc_writeb(falcbase + F_REG(LIM2, ch), (0x80 | LIM2_LOS1 | dja)); - cpc_writeb(falcbase + F_REG(XPM0, ch), 0x8e); - cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01); - cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); - break; - case PC300_LBO_22_5_DB: - cpc_writeb(falcbase + F_REG(LIM2, ch), (0xc0 | LIM2_LOS1 | dja)); - cpc_writeb(falcbase + F_REG(XPM0, ch), 0x09); - cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01); - cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); - break; - } - - /* Transmit Clock-Slot Offset */ - cpc_writeb(falcbase + F_REG(XC0, ch), - cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); - /* Transmit Time-slot Offset */ - cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e); - /* Receive Clock-Slot offset */ - cpc_writeb(falcbase + F_REG(RC0, ch), 0x05); - /* Receive Time-slot offset */ - cpc_writeb(falcbase + F_REG(RC1, ch), 0x00); - - /* LOS Detection after 176 consecutive 0s */ - cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a); - /* LOS Recovery after 22 ones in the time window of PCD */ - cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15); - - cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f); - - if (conf->fr_mode == PC300_FR_ESF_JAPAN) { - cpc_writeb(falcbase + F_REG(RC1, ch), - cpc_readb(falcbase + F_REG(RC1, ch)) | 0x80); - } - - falc_close_all_timeslots(card, ch); -} - -static void falc_init_e1(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); - - /* Switch to E1 mode (PCM 30) */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_PMOD); - - /* Clock mode */ - if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */ - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); - } else { /* Slave mode */ - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); - } - cpc_writeb(falcbase + F_REG(LOOP, ch), - cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_SFM); - - cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI); - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) & - ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1)); - - switch (conf->lcode) { - case PC300_LC_AMI: - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | - FMR0_XC1 | FMR0_RC1); - break; - - case PC300_LC_HDB3: - cpc_writeb(falcbase + F_REG(FMR0, ch), - cpc_readb(falcbase + F_REG(FMR0, ch)) | - FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1); - break; - - case PC300_LC_NRZ: - break; - } - - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0)); - /* Set interface mode to 2 MBPS */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); - - cpc_writeb(falcbase + F_REG(XPM0, ch), 0x18); - cpc_writeb(falcbase + F_REG(XPM1, ch), 0x03); - cpc_writeb(falcbase + F_REG(XPM2, ch), 0x00); - - switch (conf->fr_mode) { - case PC300_FR_MF_CRC4: - pfalc->multiframe_mode = 1; - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_XFS); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_RFS1); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0); - cpc_writeb(falcbase + F_REG(FMR3, ch), - cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_EXTIW); - - /* MultiFrame Resynchronization */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_MFCS); - - /* Automatic Loss of Multiframe > 914 CRC errors */ - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_ALMF); - - /* S1 and SI1/SI2 spare Bits set to 1 */ - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_AXS); - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_EBP); - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XS13 | XSP_XS15); - - /* Automatic Force Resynchronization */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR); - - /* Transmit Automatic Remote Alarm */ - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA); - - /* Transmit Spare Bits for National Use (Y, Sn, Sa) */ - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) | - XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4); - break; - - case PC300_FR_MF_NON_CRC4: - case PC300_FR_D4: - pfalc->multiframe_mode = 0; - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & - ~(FMR2_RFS1 | FMR2_RFS0)); - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XSIS); - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XSIF); - - /* Automatic Force Resynchronization */ - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR); - - /* Transmit Automatic Remote Alarm */ - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA); - - /* Transmit Spare Bits for National Use (Y, Sn, Sa) */ - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) | - XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4); - break; - - case PC300_FR_UNFRAMED: - pfalc->multiframe_mode = 0; - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & - ~(FMR2_RFS1 | FMR2_RFS0)); - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_TT0); - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) & - ~(XSW_XTM|XSW_XY0|XSW_XY1|XSW_XY2|XSW_XY3|XSW_XY4)); - cpc_writeb(falcbase + F_REG(TSWM, ch), 0xff); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | - (FMR2_RTM | FMR2_DAIS)); - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_AXRA); - cpc_writeb(falcbase + F_REG(FMR1, ch), - cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_AFR); - pfalc->sync = 1; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) | - (CPLD_REG2_FALC_LED2 << (2 * ch))); - break; - } - - /* No signaling */ - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_CASEN); - cpc_writeb(falcbase + F_REG(CCR1, ch), 0); - - cpc_writeb(falcbase + F_REG(LIM1, ch), - cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); - cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja)); - - /* Transmit Clock-Slot Offset */ - cpc_writeb(falcbase + F_REG(XC0, ch), - cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); - /* Transmit Time-slot Offset */ - cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e); - /* Receive Clock-Slot offset */ - cpc_writeb(falcbase + F_REG(RC0, ch), 0x05); - /* Receive Time-slot offset */ - cpc_writeb(falcbase + F_REG(RC1, ch), 0x00); - - /* LOS Detection after 176 consecutive 0s */ - cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a); - /* LOS Recovery after 22 ones in the time window of PCD */ - cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15); - - cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f); - - falc_close_all_timeslots(card, ch); -} - -static void falc_init_hdlc(pc300_t * card, int ch) -{ - void __iomem *falcbase = card->hw.falcbase; - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - - /* Enable transparent data transfer */ - if (conf->fr_mode == PC300_FR_UNFRAMED) { - cpc_writeb(falcbase + F_REG(MODE, ch), 0); - } else { - cpc_writeb(falcbase + F_REG(MODE, ch), - cpc_readb(falcbase + F_REG(MODE, ch)) | - (MODE_HRAC | MODE_MDS2)); - cpc_writeb(falcbase + F_REG(RAH2, ch), 0xff); - cpc_writeb(falcbase + F_REG(RAH1, ch), 0xff); - cpc_writeb(falcbase + F_REG(RAL2, ch), 0xff); - cpc_writeb(falcbase + F_REG(RAL1, ch), 0xff); - } - - /* Tx/Rx reset */ - falc_issue_cmd(card, ch, CMDR_RRES | CMDR_XRES | CMDR_SRES); - - /* Enable interrupt sources */ - falc_intr_enable(card, ch); -} - -static void te_config(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucchar dummy; - unsigned long flags; - - memset(pfalc, 0, sizeof(falc_t)); - switch (conf->media) { - case IF_IFACE_T1: - pfalc->num_channels = NUM_OF_T1_CHANNELS; - pfalc->offset = 1; - break; - case IF_IFACE_E1: - pfalc->num_channels = NUM_OF_E1_CHANNELS; - pfalc->offset = 0; - break; - } - if (conf->tslot_bitmap == 0xffffffffUL) - pfalc->full_bandwidth = 1; - else - pfalc->full_bandwidth = 0; - - CPC_LOCK(card, flags); - /* Reset the FALC chip */ - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) | - (CPLD_REG1_FALC_RESET << (2 * ch))); - udelay(10000); - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) & - ~(CPLD_REG1_FALC_RESET << (2 * ch))); - - if (conf->media == IF_IFACE_T1) { - falc_init_t1(card, ch); - } else { - falc_init_e1(card, ch); - } - falc_init_hdlc(card, ch); - if (conf->rx_sens == PC300_RX_SENS_SH) { - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_EQON); - } else { - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_EQON); - } - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) | - ((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK) << (2 * ch))); - - /* Clear all interrupt registers */ - dummy = cpc_readb(falcbase + F_REG(FISR0, ch)) + - cpc_readb(falcbase + F_REG(FISR1, ch)) + - cpc_readb(falcbase + F_REG(FISR2, ch)) + - cpc_readb(falcbase + F_REG(FISR3, ch)); - CPC_UNLOCK(card, flags); -} - -static void falc_check_status(pc300_t * card, int ch, unsigned char frs0) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - /* Verify LOS */ - if (frs0 & FRS0_LOS) { - if (!pfalc->red_alarm) { - pfalc->red_alarm = 1; - pfalc->los++; - if (!pfalc->blue_alarm) { - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise interfere - * with other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) - | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - } - } - } else { - if (pfalc->red_alarm) { - pfalc->red_alarm = 0; - pfalc->losr++; - } - } - - if (conf->fr_mode != PC300_FR_UNFRAMED) { - /* Verify AIS alarm */ - if (frs0 & FRS0_AIS) { - if (!pfalc->blue_alarm) { - pfalc->blue_alarm = 1; - pfalc->ais++; - // EVENT_AIS - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise interfere with other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_AIS - } - } else { - pfalc->blue_alarm = 0; - } - - /* Verify LFA */ - if (frs0 & FRS0_LFA) { - if (!pfalc->loss_fa) { - pfalc->loss_fa = 1; - pfalc->lfa++; - if (!pfalc->blue_alarm && !pfalc->red_alarm) { - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise - * interfere with other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) - | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - } - } - } else { - if (pfalc->loss_fa) { - pfalc->loss_fa = 0; - pfalc->farec++; - } - } - - /* Verify LMFA */ - if (pfalc->multiframe_mode && (frs0 & FRS0_LMFA)) { - /* D4 or CRC4 frame mode */ - if (!pfalc->loss_mfa) { - pfalc->loss_mfa = 1; - pfalc->lmfa++; - if (!pfalc->blue_alarm && !pfalc->red_alarm && - !pfalc->loss_fa) { - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise - * interfere with other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) - | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - } - } - } else { - pfalc->loss_mfa = 0; - } - - /* Verify Remote Alarm */ - if (frs0 & FRS0_RRA) { - if (!pfalc->yellow_alarm) { - pfalc->yellow_alarm = 1; - pfalc->rai++; - if (pfalc->sync) { - // EVENT_RAI - falc_disable_comm(card, ch); - // EVENT_RAI - } - } - } else { - pfalc->yellow_alarm = 0; - } - } /* if !PC300_UNFRAMED */ - - if (pfalc->red_alarm || pfalc->loss_fa || - pfalc->loss_mfa || pfalc->blue_alarm) { - if (pfalc->sync) { - pfalc->sync = 0; - chan->d.line_off++; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED2 << (2 * ch))); - } - } else { - if (!pfalc->sync) { - pfalc->sync = 1; - chan->d.line_on++; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) | - (CPLD_REG2_FALC_LED2 << (2 * ch))); - } - } - - if (pfalc->sync && !pfalc->yellow_alarm) { - if (!pfalc->active) { - // EVENT_FALC_NORMAL - if (pfalc->loop_active) { - return; - } - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) & ~IMR0_PDEN); - } - falc_enable_comm(card, ch); - // EVENT_FALC_NORMAL - pfalc->active = 1; - } - } else { - if (pfalc->active) { - pfalc->active = 0; - } - } -} - -static void falc_update_stats(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucshort counter; - - counter = cpc_readb(falcbase + F_REG(FECL, ch)); - counter |= cpc_readb(falcbase + F_REG(FECH, ch)) << 8; - pfalc->fec += counter; - - counter = cpc_readb(falcbase + F_REG(CVCL, ch)); - counter |= cpc_readb(falcbase + F_REG(CVCH, ch)) << 8; - pfalc->cvc += counter; - - counter = cpc_readb(falcbase + F_REG(CECL, ch)); - counter |= cpc_readb(falcbase + F_REG(CECH, ch)) << 8; - pfalc->cec += counter; - - counter = cpc_readb(falcbase + F_REG(EBCL, ch)); - counter |= cpc_readb(falcbase + F_REG(EBCH, ch)) << 8; - pfalc->ebc += counter; - - if (cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) { - mdelay(10); - counter = cpc_readb(falcbase + F_REG(BECL, ch)); - counter |= cpc_readb(falcbase + F_REG(BECH, ch)) << 8; - pfalc->bec += counter; - - if (((conf->media == IF_IFACE_T1) && - (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_LLBAD) && - (!(cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN))) - || - ((conf->media == IF_IFACE_E1) && - (cpc_readb(falcbase + F_REG(RSP, ch)) & RSP_LLBAD))) { - pfalc->prbs = 2; - } else { - pfalc->prbs = 1; - } - } -} - -/*---------------------------------------------------------------------------- - * falc_remote_loop - *---------------------------------------------------------------------------- - * Description: In the remote loopback mode the clock and data recovered - * from the line inputs RL1/2 or RDIP/RDIN are routed back - * to the line outputs XL1/2 or XDOP/XDON via the analog - * transmitter. As in normal mode they are processsed by - * the synchronizer and then sent to the system interface. - *---------------------------------------------------------------------------- - */ -static void falc_remote_loop(pc300_t * card, int ch, int loop_on) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (loop_on) { - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise interfere with - * other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - cpc_writeb(falcbase + F_REG(LIM1, ch), - cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL); - pfalc->loop_active = 1; - } else { - cpc_writeb(falcbase + F_REG(LIM1, ch), - cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL); - pfalc->sync = 0; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED2 << (2 * ch))); - pfalc->active = 0; - falc_issue_cmd(card, ch, CMDR_XRES); - pfalc->loop_active = 0; - } -} - -/*---------------------------------------------------------------------------- - * falc_local_loop - *---------------------------------------------------------------------------- - * Description: The local loopback mode disconnects the receive lines - * RL1/RL2 resp. RDIP/RDIN from the receiver. Instead of the - * signals coming from the line the data provided by system - * interface are routed through the analog receiver back to - * the system interface. The unipolar bit stream will be - * undisturbed transmitted on the line. Receiver and transmitter - * coding must be identical. - *---------------------------------------------------------------------------- - */ -static void falc_local_loop(pc300_t * card, int ch, int loop_on) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (loop_on) { - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_LL); - pfalc->loop_active = 1; - } else { - cpc_writeb(falcbase + F_REG(LIM0, ch), - cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_LL); - pfalc->loop_active = 0; - } -} - -/*---------------------------------------------------------------------------- - * falc_payload_loop - *---------------------------------------------------------------------------- - * Description: This routine allows to enable/disable payload loopback. - * When the payload loop is activated, the received 192 bits - * of payload data will be looped back to the transmit - * direction. The framing bits, CRC6 and DL bits are not - * looped. They are originated by the FALC-LH transmitter. - *---------------------------------------------------------------------------- - */ -static void falc_payload_loop(pc300_t * card, int ch, int loop_on) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (loop_on) { - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise interfere with - * other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_PLB); - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR4, ch), - cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_TM); - } else { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) | XSP_TT0); - } - falc_open_all_timeslots(card, ch); - pfalc->loop_active = 2; - } else { - cpc_writeb(falcbase + F_REG(FMR2, ch), - cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_PLB); - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR4, ch), - cpc_readb(falcbase + F_REG(FMR4, ch)) & ~FMR4_TM); - } else { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) & ~XSP_TT0); - } - pfalc->sync = 0; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED2 << (2 * ch))); - pfalc->active = 0; - falc_issue_cmd(card, ch, CMDR_XRES); - pfalc->loop_active = 0; - } -} - -/*---------------------------------------------------------------------------- - * turn_off_xlu - *---------------------------------------------------------------------------- - * Description: Turns XLU bit off in the proper register - *---------------------------------------------------------------------------- - */ -static void turn_off_xlu(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - void __iomem *falcbase = card->hw.falcbase; - - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLU); - } else { - cpc_writeb(falcbase + F_REG(FMR3, ch), - cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLU); - } -} - -/*---------------------------------------------------------------------------- - * turn_off_xld - *---------------------------------------------------------------------------- - * Description: Turns XLD bit off in the proper register - *---------------------------------------------------------------------------- - */ -static void turn_off_xld(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - void __iomem *falcbase = card->hw.falcbase; - - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLD); - } else { - cpc_writeb(falcbase + F_REG(FMR3, ch), - cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLD); - } -} - -/*---------------------------------------------------------------------------- - * falc_generate_loop_up_code - *---------------------------------------------------------------------------- - * Description: This routine writes the proper FALC chip register in order - * to generate a LOOP activation code over a T1/E1 line. - *---------------------------------------------------------------------------- - */ -static void falc_generate_loop_up_code(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLU); - } else { - cpc_writeb(falcbase + F_REG(FMR3, ch), - cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLU); - } - // EVENT_FALC_ABNORMAL - if (conf->media == IF_IFACE_T1) { - /* Disable this interrupt as it may otherwise interfere with - * other working boards. */ - cpc_writeb(falcbase + F_REG(IMR0, ch), - cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); - } - falc_disable_comm(card, ch); - // EVENT_FALC_ABNORMAL - pfalc->loop_gen = 1; -} - -/*---------------------------------------------------------------------------- - * falc_generate_loop_down_code - *---------------------------------------------------------------------------- - * Description: This routine writes the proper FALC chip register in order - * to generate a LOOP deactivation code over a T1/E1 line. - *---------------------------------------------------------------------------- - */ -static void falc_generate_loop_down_code(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (conf->media == IF_IFACE_T1) { - cpc_writeb(falcbase + F_REG(FMR5, ch), - cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLD); - } else { - cpc_writeb(falcbase + F_REG(FMR3, ch), - cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLD); - } - pfalc->sync = 0; - cpc_writeb(falcbase + card->hw.cpld_reg2, - cpc_readb(falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED2 << (2 * ch))); - pfalc->active = 0; -//? falc_issue_cmd(card, ch, CMDR_XRES); - pfalc->loop_gen = 0; -} - -/*---------------------------------------------------------------------------- - * falc_pattern_test - *---------------------------------------------------------------------------- - * Description: This routine generates a pattern code and checks - * it on the reception side. - *---------------------------------------------------------------------------- - */ -static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (activate) { - pfalc->prbs = 1; - pfalc->bec = 0; - if (conf->media == IF_IFACE_T1) { - /* Disable local loop activation/deactivation detect */ - cpc_writeb(falcbase + F_REG(IMR3, ch), - cpc_readb(falcbase + F_REG(IMR3, ch)) | IMR3_LLBSC); - } else { - /* Disable local loop activation/deactivation detect */ - cpc_writeb(falcbase + F_REG(IMR1, ch), - cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_LLBSC); - } - /* Activates generation and monitoring of PRBS - * (Pseudo Random Bit Sequence) */ - cpc_writeb(falcbase + F_REG(LCR1, ch), - cpc_readb(falcbase + F_REG(LCR1, ch)) | LCR1_EPRM | LCR1_XPRBS); - } else { - pfalc->prbs = 0; - /* Deactivates generation and monitoring of PRBS - * (Pseudo Random Bit Sequence) */ - cpc_writeb(falcbase + F_REG(LCR1, ch), - cpc_readb(falcbase+F_REG(LCR1,ch)) & ~(LCR1_EPRM | LCR1_XPRBS)); - if (conf->media == IF_IFACE_T1) { - /* Enable local loop activation/deactivation detect */ - cpc_writeb(falcbase + F_REG(IMR3, ch), - cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC); - } else { - /* Enable local loop activation/deactivation detect */ - cpc_writeb(falcbase + F_REG(IMR1, ch), - cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC); - } - } -} - -/*---------------------------------------------------------------------------- - * falc_pattern_test_error - *---------------------------------------------------------------------------- - * Description: This routine returns the bit error counter value - *---------------------------------------------------------------------------- - */ -static ucshort falc_pattern_test_error(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - - return (pfalc->bec); -} - -/**********************************/ -/*** Net Interface Routines ***/ -/**********************************/ - -static void -cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx) -{ - struct sk_buff *skb; - - if ((skb = dev_alloc_skb(10 + skb_main->len)) == NULL) { - printk("%s: out of memory\n", dev->name); - return; - } - skb_put(skb, 10 + skb_main->len); - - skb->dev = dev; - skb->protocol = htons(ETH_P_CUST); - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_HOST; - skb->len = 10 + skb_main->len; - - skb_copy_to_linear_data(skb, dev->name, 5); - skb->data[5] = '['; - skb->data[6] = rx_tx; - skb->data[7] = ']'; - skb->data[8] = ':'; - skb->data[9] = ' '; - skb_copy_from_linear_data(skb_main, &skb->data[10], skb_main->len); - - netif_rx(skb); -} - -static void cpc_tx_timeout(struct net_device *dev) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = hdlc_stats(dev); - int ch = chan->channel; - unsigned long flags; - ucchar ilar; - - stats->tx_errors++; - stats->tx_aborted_errors++; - CPC_LOCK(card, flags); - if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) { - printk("%s: ILAR=0x%x\n", dev->name, ilar); - cpc_writeb(card->hw.scabase + ILAR, ilar); - cpc_writeb(card->hw.scabase + DMER, 0x80); - } - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED1 << (2 * ch))); - } - dev->trans_start = jiffies; - CPC_UNLOCK(card, flags); - netif_wake_queue(dev); -} - -static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = hdlc_stats(dev); - int ch = chan->channel; - unsigned long flags; -#ifdef PC300_DEBUG_TX - int i; -#endif - - if (chan->conf.monitor) { - /* In monitor mode no Tx is done: ignore packet */ - dev_kfree_skb(skb); - return 0; - } else if (!netif_carrier_ok(dev)) { - /* DCD must be OFF: drop packet */ - dev_kfree_skb(skb); - stats->tx_errors++; - stats->tx_carrier_errors++; - return 0; - } else if (cpc_readb(card->hw.scabase + M_REG(ST3, ch)) & ST3_DCD) { - printk("%s: DCD is OFF. Going administrative down.\n", dev->name); - stats->tx_errors++; - stats->tx_carrier_errors++; - dev_kfree_skb(skb); - netif_carrier_off(dev); - CPC_LOCK(card, flags); - cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED1 << (2 * ch))); - } - CPC_UNLOCK(card, flags); - netif_wake_queue(dev); - return 0; - } - - /* Write buffer to DMA buffers */ - if (dma_buf_write(card, ch, (ucchar *) skb->data, skb->len) != 0) { -// printk("%s: write error. Dropping TX packet.\n", dev->name); - netif_stop_queue(dev); - dev_kfree_skb(skb); - stats->tx_errors++; - stats->tx_dropped++; - return 0; - } -#ifdef PC300_DEBUG_TX - printk("%s T:", dev->name); - for (i = 0; i < skb->len; i++) - printk(" %02x", *(skb->data + i)); - printk("\n"); -#endif - - if (d->trace_on) { - cpc_trace(dev, skb, 'T'); - } - dev->trans_start = jiffies; - - /* Start transmission */ - CPC_LOCK(card, flags); - /* verify if it has more than one free descriptor */ - if (card->chan[ch].nfree_tx_bd <= 1) { - /* don't have so stop the queue */ - netif_stop_queue(dev); - } - cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch), - TX_BD_ADDR(ch, chan->tx_next_bd)); - cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA); - cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE); - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) | - (CPLD_REG2_FALC_LED1 << (2 * ch))); - } - CPC_UNLOCK(card, flags); - dev_kfree_skb(skb); - - return 0; -} - -static void cpc_net_rx(struct net_device *dev) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = hdlc_stats(dev); - int ch = chan->channel; -#ifdef PC300_DEBUG_RX - int i; -#endif - int rxb; - struct sk_buff *skb; - - while (1) { - if ((rxb = dma_get_rx_frame_size(card, ch)) == -1) - return; - - if (!netif_carrier_ok(dev)) { - /* DCD must be OFF: drop packet */ - printk("%s : DCD is OFF - drop %d rx bytes\n", dev->name, rxb); - skb = NULL; - } else { - if (rxb > (dev->mtu + 40)) { /* add headers */ - printk("%s : MTU exceeded %d\n", dev->name, rxb); - skb = NULL; - } else { - skb = dev_alloc_skb(rxb); - if (skb == NULL) { - printk("%s: Memory squeeze!!\n", dev->name); - return; - } - skb->dev = dev; - } - } - - if (((rxb = dma_buf_read(card, ch, skb)) <= 0) || (skb == NULL)) { -#ifdef PC300_DEBUG_RX - printk("%s: rxb = %x\n", dev->name, rxb); -#endif - if ((skb == NULL) && (rxb > 0)) { - /* rxb > dev->mtu */ - stats->rx_errors++; - stats->rx_length_errors++; - continue; - } - - if (rxb < 0) { /* Invalid frame */ - rxb = -rxb; - if (rxb & DST_OVR) { - stats->rx_errors++; - stats->rx_fifo_errors++; - } - if (rxb & DST_CRC) { - stats->rx_errors++; - stats->rx_crc_errors++; - } - if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) { - stats->rx_errors++; - stats->rx_frame_errors++; - } - } - if (skb) { - dev_kfree_skb_irq(skb); - } - continue; - } - - stats->rx_bytes += rxb; - -#ifdef PC300_DEBUG_RX - printk("%s R:", dev->name); - for (i = 0; i < skb->len; i++) - printk(" %02x", *(skb->data + i)); - printk("\n"); -#endif - if (d->trace_on) { - cpc_trace(dev, skb, 'R'); - } - stats->rx_packets++; - skb->protocol = hdlc_type_trans(skb, dev); - netif_rx(skb); - } -} - -/************************************/ -/*** PC300 Interrupt Routines ***/ -/************************************/ -static void sca_tx_intr(pc300dev_t *dev) -{ - pc300ch_t *chan = (pc300ch_t *)dev->chan; - pc300_t *card = (pc300_t *)chan->card; - int ch = chan->channel; - volatile pcsca_bd_t __iomem * ptdescr; - struct net_device_stats *stats = hdlc_stats(dev->dev); - - /* Clean up descriptors from previous transmission */ - ptdescr = (card->hw.rambase + - TX_BD_ADDR(ch,chan->tx_first_bd)); - while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != - TX_BD_ADDR(ch,chan->tx_first_bd)) && - (cpc_readb(&ptdescr->status) & DST_OSB)) { - stats->tx_packets++; - stats->tx_bytes += cpc_readw(&ptdescr->len); - cpc_writeb(&ptdescr->status, DST_OSB); - cpc_writew(&ptdescr->len, 0); - chan->nfree_tx_bd++; - chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1); - ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd)); - } - -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto == PC300_PROTO_MLPPP) { - cpc_tty_trigger_poll(dev); - } else { -#endif - /* Tell the upper layer we are ready to transmit more packets */ - netif_wake_queue(dev->dev); -#ifdef CONFIG_PC300_MLPPP - } -#endif -} - -static void sca_intr(pc300_t * card) -{ - void __iomem *scabase = card->hw.scabase; - volatile uclong status; - int ch; - int intr_count = 0; - unsigned char dsr_rx; - - while ((status = cpc_readl(scabase + ISR0)) != 0) { - for (ch = 0; ch < card->hw.nchan; ch++) { - pc300ch_t *chan = &card->chan[ch]; - pc300dev_t *d = &chan->d; - struct net_device *dev = d->dev; - - spin_lock(&card->card_lock); - - /**** Reception ****/ - if (status & IR0_DRX((IR0_DMIA | IR0_DMIB), ch)) { - ucchar drx_stat = cpc_readb(scabase + DSR_RX(ch)); - - /* Clear RX interrupts */ - cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE); - -#ifdef PC300_DEBUG_INTR - printk ("sca_intr: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n", - ch, status, drx_stat); -#endif - if (status & IR0_DRX(IR0_DMIA, ch)) { - if (drx_stat & DSR_BOF) { -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto == PC300_PROTO_MLPPP) { - /* verify if driver is TTY */ - if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { - rx_dma_stop(card, ch); - } - cpc_tty_receive(d); - rx_dma_start(card, ch); - } else -#endif - { - if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { - rx_dma_stop(card, ch); - } - cpc_net_rx(dev); - /* Discard invalid frames */ - 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); - } - } - } - if (status & IR0_DRX(IR0_DMIB, ch)) { - if (drx_stat & DSR_EOM) { - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + - card->hw.cpld_reg2, - cpc_readb (card->hw.falcbase + - card->hw.cpld_reg2) | - (CPLD_REG2_FALC_LED1 << (2 * ch))); - } -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto == PC300_PROTO_MLPPP) { - /* verify if driver is TTY */ - cpc_tty_receive(d); - } else { - cpc_net_rx(dev); - } -#else - cpc_net_rx(dev); -#endif - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + - card->hw.cpld_reg2, - cpc_readb (card->hw.falcbase + - card->hw.cpld_reg2) & - ~ (CPLD_REG2_FALC_LED1 << (2 * ch))); - } - } - } - if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { -#ifdef PC300_DEBUG_INTR - printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", - dev->name, ch, status, drx_stat, dsr_rx); -#endif - cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe); - } - } - - /**** Transmission ****/ - if (status & IR0_DTX((IR0_EFT | IR0_DMIA | IR0_DMIB), ch)) { - ucchar dtx_stat = cpc_readb(scabase + DSR_TX(ch)); - - /* Clear TX interrupts */ - cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE); - -#ifdef PC300_DEBUG_INTR - printk ("sca_intr: TX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n", - ch, status, dtx_stat); -#endif - if (status & IR0_DTX(IR0_EFT, ch)) { - if (dtx_stat & DSR_UDRF) { - if (cpc_readb (scabase + M_REG(TBN, ch)) != 0) { - cpc_writeb(scabase + M_REG(CMD,ch), CMD_TX_BUF_CLR); - } - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb (card->hw.falcbase + - card->hw.cpld_reg2) & - ~ (CPLD_REG2_FALC_LED1 << (2 * ch))); - } - hdlc_stats(dev)->tx_errors++; - hdlc_stats(dev)->tx_fifo_errors++; - sca_tx_intr(d); - } - } - if (status & IR0_DTX(IR0_DMIA, ch)) { - if (dtx_stat & DSR_BOF) { - } - } - if (status & IR0_DTX(IR0_DMIB, ch)) { - if (dtx_stat & DSR_EOM) { - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb (card->hw.falcbase + - card->hw.cpld_reg2) & - ~ (CPLD_REG2_FALC_LED1 << (2 * ch))); - } - sca_tx_intr(d); - } - } - } - - /**** MSCI ****/ - if (status & IR0_M(IR0_RXINTA, ch)) { - ucchar st1 = cpc_readb(scabase + M_REG(ST1, ch)); - - /* Clear MSCI interrupts */ - cpc_writeb(scabase + M_REG(ST1, ch), st1); - -#ifdef PC300_DEBUG_INTR - printk("sca_intr: MSCI intr chan[%d] (st=0x%08lx, st1=0x%02x)\n", - ch, status, st1); -#endif - if (st1 & ST1_CDCD) { /* DCD changed */ - if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) { - printk ("%s: DCD is OFF. Going administrative down.\n", - dev->name); -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto != PC300_PROTO_MLPPP) { - netif_carrier_off(dev); - } -#else - netif_carrier_off(dev); - -#endif - card->chan[ch].d.line_off++; - } else { /* DCD = 1 */ - printk ("%s: DCD is ON. Going administrative up.\n", - dev->name); -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto != PC300_PROTO_MLPPP) - /* verify if driver is not TTY */ -#endif - netif_carrier_on(dev); - card->chan[ch].d.line_on++; - } - } - } - spin_unlock(&card->card_lock); - } - if (++intr_count == 10) - /* Too much work at this board. Force exit */ - break; - } -} - -static void falc_t1_loop_detection(pc300_t * card, int ch, ucchar frs1) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && - !pfalc->loop_gen) { - if (frs1 & FRS1_LLBDD) { - // A Line Loop Back Deactivation signal detected - if (pfalc->loop_active) { - falc_remote_loop(card, ch, 0); - } - } else { - if ((frs1 & FRS1_LLBAD) && - ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) { - // A Line Loop Back Activation signal detected - if (!pfalc->loop_active) { - falc_remote_loop(card, ch, 1); - } - } - } - } -} - -static void falc_e1_loop_detection(pc300_t * card, int ch, ucchar rsp) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - - if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && - !pfalc->loop_gen) { - if (rsp & RSP_LLBDD) { - // A Line Loop Back Deactivation signal detected - if (pfalc->loop_active) { - falc_remote_loop(card, ch, 0); - } - } else { - if ((rsp & RSP_LLBAD) && - ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) { - // A Line Loop Back Activation signal detected - if (!pfalc->loop_active) { - falc_remote_loop(card, ch, 1); - } - } - } - } -} - -static void falc_t1_intr(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucchar isr0, isr3, gis; - ucchar dummy; - - while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) { - if (gis & GIS_ISR0) { - isr0 = cpc_readb(falcbase + F_REG(FISR0, ch)); - if (isr0 & FISR0_PDEN) { - /* Read the bit to clear the situation */ - if (cpc_readb(falcbase + F_REG(FRS1, ch)) & - FRS1_PDEN) { - pfalc->pden++; - } - } - } - - if (gis & GIS_ISR1) { - dummy = cpc_readb(falcbase + F_REG(FISR1, ch)); - } - - if (gis & GIS_ISR2) { - dummy = cpc_readb(falcbase + F_REG(FISR2, ch)); - } - - if (gis & GIS_ISR3) { - isr3 = cpc_readb(falcbase + F_REG(FISR3, ch)); - if (isr3 & FISR3_SEC) { - pfalc->sec++; - falc_update_stats(card, ch); - falc_check_status(card, ch, - cpc_readb(falcbase + F_REG(FRS0, ch))); - } - if (isr3 & FISR3_ES) { - pfalc->es++; - } - if (isr3 & FISR3_LLBSC) { - falc_t1_loop_detection(card, ch, - cpc_readb(falcbase + F_REG(FRS1, ch))); - } - } - } -} - -static void falc_e1_intr(pc300_t * card, int ch) -{ - pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - void __iomem *falcbase = card->hw.falcbase; - ucchar isr1, isr2, isr3, gis, rsp; - ucchar dummy; - - while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) { - rsp = cpc_readb(falcbase + F_REG(RSP, ch)); - - if (gis & GIS_ISR0) { - dummy = cpc_readb(falcbase + F_REG(FISR0, ch)); - } - if (gis & GIS_ISR1) { - isr1 = cpc_readb(falcbase + F_REG(FISR1, ch)); - if (isr1 & FISR1_XMB) { - if ((pfalc->xmb_cause & 2) - && pfalc->multiframe_mode) { - if (cpc_readb (falcbase + F_REG(FRS0, ch)) & - (FRS0_LOS | FRS0_AIS | FRS0_LFA)) { - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) - & ~XSP_AXS); - } else { - cpc_writeb(falcbase + F_REG(XSP, ch), - cpc_readb(falcbase + F_REG(XSP, ch)) - | XSP_AXS); - } - } - pfalc->xmb_cause = 0; - cpc_writeb(falcbase + F_REG(IMR1, ch), - cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_XMB); - } - if (isr1 & FISR1_LLBSC) { - falc_e1_loop_detection(card, ch, rsp); - } - } - if (gis & GIS_ISR2) { - isr2 = cpc_readb(falcbase + F_REG(FISR2, ch)); - if (isr2 & FISR2_T400MS) { - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XRA); - } - if (isr2 & FISR2_MFAR) { - cpc_writeb(falcbase + F_REG(XSW, ch), - cpc_readb(falcbase + F_REG(XSW, ch)) & ~XSW_XRA); - } - if (isr2 & (FISR2_FAR | FISR2_LFA | FISR2_AIS | FISR2_LOS)) { - pfalc->xmb_cause |= 2; - cpc_writeb(falcbase + F_REG(IMR1, ch), - cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_XMB); - } - } - if (gis & GIS_ISR3) { - isr3 = cpc_readb(falcbase + F_REG(FISR3, ch)); - if (isr3 & FISR3_SEC) { - pfalc->sec++; - falc_update_stats(card, ch); - falc_check_status(card, ch, - cpc_readb(falcbase + F_REG(FRS0, ch))); - } - if (isr3 & FISR3_ES) { - pfalc->es++; - } - } - } -} - -static void falc_intr(pc300_t * card) -{ - int ch; - - for (ch = 0; ch < card->hw.nchan; ch++) { - pc300ch_t *chan = &card->chan[ch]; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - - if (conf->media == IF_IFACE_T1) { - falc_t1_intr(card, ch); - } else { - falc_e1_intr(card, ch); - } - } -} - -static irqreturn_t cpc_intr(int irq, void *dev_id) -{ - pc300_t *card = dev_id; - volatile ucchar plx_status; - - if (!card) { -#ifdef PC300_DEBUG_INTR - printk("cpc_intr: spurious intr %d\n", irq); -#endif - return IRQ_NONE; /* spurious intr */ - } - - if (!card->hw.rambase) { -#ifdef PC300_DEBUG_INTR - printk("cpc_intr: spurious intr2 %d\n", irq); -#endif - return IRQ_NONE; /* spurious intr */ - } - - switch (card->hw.type) { - case PC300_RSV: - case PC300_X21: - sca_intr(card); - break; - - case PC300_TE: - while ( (plx_status = (cpc_readb(card->hw.plxbase + card->hw.intctl_reg) & - (PLX_9050_LINT1_STATUS | PLX_9050_LINT2_STATUS))) != 0) { - if (plx_status & PLX_9050_LINT1_STATUS) { /* SCA Interrupt */ - sca_intr(card); - } - if (plx_status & PLX_9050_LINT2_STATUS) { /* FALC Interrupt */ - falc_intr(card); - } - } - break; - } - return IRQ_HANDLED; -} - -static void cpc_sca_status(pc300_t * card, int ch) -{ - ucchar ilar; - void __iomem *scabase = card->hw.scabase; - unsigned long flags; - - tx_dma_buf_check(card, ch); - rx_dma_buf_check(card, ch); - ilar = cpc_readb(scabase + ILAR); - printk ("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n", - ilar, cpc_readb(scabase + WCRL), cpc_readb(scabase + PCR), - cpc_readb(scabase + BTCR), cpc_readb(scabase + BOLR)); - printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n", - cpc_readl(scabase + DTX_REG(CDAL, ch)), - cpc_readl(scabase + DTX_REG(EDAL, ch))); - printk("RX_CDA=0x%08x, RX_EDA=0x%08x, BFL=0x%04x\n", - cpc_readl(scabase + DRX_REG(CDAL, ch)), - cpc_readl(scabase + DRX_REG(EDAL, ch)), - cpc_readw(scabase + DRX_REG(BFLL, ch))); - printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n", - cpc_readb(scabase + DMER), cpc_readb(scabase + DSR_TX(ch)), - cpc_readb(scabase + DSR_RX(ch))); - printk("DMR_TX=0x%02x, DMR_RX=0x%02x, DIR_TX=0x%02x, DIR_RX=0x%02x\n", - cpc_readb(scabase + DMR_TX(ch)), cpc_readb(scabase + DMR_RX(ch)), - cpc_readb(scabase + DIR_TX(ch)), - cpc_readb(scabase + DIR_RX(ch))); - printk("DCR_TX=0x%02x, DCR_RX=0x%02x, FCT_TX=0x%02x, FCT_RX=0x%02x\n", - cpc_readb(scabase + DCR_TX(ch)), cpc_readb(scabase + DCR_RX(ch)), - cpc_readb(scabase + FCT_TX(ch)), - cpc_readb(scabase + FCT_RX(ch))); - printk("MD0=0x%02x, MD1=0x%02x, MD2=0x%02x, MD3=0x%02x, IDL=0x%02x\n", - cpc_readb(scabase + M_REG(MD0, ch)), - cpc_readb(scabase + M_REG(MD1, ch)), - cpc_readb(scabase + M_REG(MD2, ch)), - cpc_readb(scabase + M_REG(MD3, ch)), - cpc_readb(scabase + M_REG(IDL, ch))); - printk("CMD=0x%02x, SA0=0x%02x, SA1=0x%02x, TFN=0x%02x, CTL=0x%02x\n", - cpc_readb(scabase + M_REG(CMD, ch)), - cpc_readb(scabase + M_REG(SA0, ch)), - cpc_readb(scabase + M_REG(SA1, ch)), - cpc_readb(scabase + M_REG(TFN, ch)), - cpc_readb(scabase + M_REG(CTL, ch))); - printk("ST0=0x%02x, ST1=0x%02x, ST2=0x%02x, ST3=0x%02x, ST4=0x%02x\n", - cpc_readb(scabase + M_REG(ST0, ch)), - cpc_readb(scabase + M_REG(ST1, ch)), - cpc_readb(scabase + M_REG(ST2, ch)), - cpc_readb(scabase + M_REG(ST3, ch)), - cpc_readb(scabase + M_REG(ST4, ch))); - printk ("CST0=0x%02x, CST1=0x%02x, CST2=0x%02x, CST3=0x%02x, FST=0x%02x\n", - cpc_readb(scabase + M_REG(CST0, ch)), - cpc_readb(scabase + M_REG(CST1, ch)), - cpc_readb(scabase + M_REG(CST2, ch)), - cpc_readb(scabase + M_REG(CST3, ch)), - cpc_readb(scabase + M_REG(FST, ch))); - printk("TRC0=0x%02x, TRC1=0x%02x, RRC=0x%02x, TBN=0x%02x, RBN=0x%02x\n", - cpc_readb(scabase + M_REG(TRC0, ch)), - cpc_readb(scabase + M_REG(TRC1, ch)), - cpc_readb(scabase + M_REG(RRC, ch)), - cpc_readb(scabase + M_REG(TBN, ch)), - cpc_readb(scabase + M_REG(RBN, ch))); - printk("TFS=0x%02x, TNR0=0x%02x, TNR1=0x%02x, RNR=0x%02x\n", - cpc_readb(scabase + M_REG(TFS, ch)), - cpc_readb(scabase + M_REG(TNR0, ch)), - cpc_readb(scabase + M_REG(TNR1, ch)), - cpc_readb(scabase + M_REG(RNR, ch))); - printk("TCR=0x%02x, RCR=0x%02x, TNR1=0x%02x, RNR=0x%02x\n", - cpc_readb(scabase + M_REG(TCR, ch)), - cpc_readb(scabase + M_REG(RCR, ch)), - cpc_readb(scabase + M_REG(TNR1, ch)), - cpc_readb(scabase + M_REG(RNR, ch))); - printk("TXS=0x%02x, RXS=0x%02x, EXS=0x%02x, TMCT=0x%02x, TMCR=0x%02x\n", - cpc_readb(scabase + M_REG(TXS, ch)), - cpc_readb(scabase + M_REG(RXS, ch)), - cpc_readb(scabase + M_REG(EXS, ch)), - cpc_readb(scabase + M_REG(TMCT, ch)), - cpc_readb(scabase + M_REG(TMCR, ch))); - printk("IE0=0x%02x, IE1=0x%02x, IE2=0x%02x, IE4=0x%02x, FIE=0x%02x\n", - cpc_readb(scabase + M_REG(IE0, ch)), - cpc_readb(scabase + M_REG(IE1, ch)), - cpc_readb(scabase + M_REG(IE2, ch)), - cpc_readb(scabase + M_REG(IE4, ch)), - cpc_readb(scabase + M_REG(FIE, ch))); - printk("IER0=0x%08x\n", cpc_readl(scabase + IER0)); - - if (ilar != 0) { - CPC_LOCK(card, flags); - cpc_writeb(scabase + ILAR, ilar); - cpc_writeb(scabase + DMER, 0x80); - CPC_UNLOCK(card, flags); - } -} - -static void cpc_falc_status(pc300_t * card, int ch) -{ - pc300ch_t *chan = &card->chan[ch]; - falc_t *pfalc = (falc_t *) & chan->falc; - unsigned long flags; - - CPC_LOCK(card, flags); - printk("CH%d: %s %s %d channels\n", - ch, (pfalc->sync ? "SYNC" : ""), (pfalc->active ? "ACTIVE" : ""), - pfalc->num_channels); - - printk(" pden=%d, los=%d, losr=%d, lfa=%d, farec=%d\n", - pfalc->pden, pfalc->los, pfalc->losr, pfalc->lfa, pfalc->farec); - printk(" lmfa=%d, ais=%d, sec=%d, es=%d, rai=%d\n", - pfalc->lmfa, pfalc->ais, pfalc->sec, pfalc->es, pfalc->rai); - printk(" bec=%d, fec=%d, cvc=%d, cec=%d, ebc=%d\n", - pfalc->bec, pfalc->fec, pfalc->cvc, pfalc->cec, pfalc->ebc); - - printk("\n"); - printk(" STATUS: %s %s %s %s %s %s\n", - (pfalc->red_alarm ? "RED" : ""), - (pfalc->blue_alarm ? "BLU" : ""), - (pfalc->yellow_alarm ? "YEL" : ""), - (pfalc->loss_fa ? "LFA" : ""), - (pfalc->loss_mfa ? "LMF" : ""), (pfalc->prbs ? "PRB" : "")); - CPC_UNLOCK(card, flags); -} - -static int cpc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - pc300conf_t conf_aux; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - int ch = chan->channel; - void __user *arg = ifr->ifr_data; - struct if_settings *settings = &ifr->ifr_settings; - void __iomem *scabase = card->hw.scabase; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch (cmd) { - case SIOCGPC300CONF: -#ifdef CONFIG_PC300_MLPPP - if (conf->proto != PC300_PROTO_MLPPP) { - conf->proto = /* FIXME hdlc->proto.id */ 0; - } -#else - 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)); - if (!arg || - copy_to_user(arg, &conf_aux, sizeof(pc300conf_t))) - return -EINVAL; - return 0; - case SIOCSPC300CONF: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!arg || - copy_from_user(&conf_aux.conf, arg, sizeof(pc300chconf_t))) - return -EINVAL; - if (card->hw.cpld_id < 0x02 && - conf_aux.conf.fr_mode == PC300_FR_UNFRAMED) { - /* CPLD_ID < 0x02 doesn't support Unframed E1 */ - return -EINVAL; - } -#ifdef CONFIG_PC300_MLPPP - if (conf_aux.conf.proto == PC300_PROTO_MLPPP) { - if (conf->proto != PC300_PROTO_MLPPP) { - memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t)); - cpc_tty_init(d); /* init TTY driver */ - } - } else { - if (conf_aux.conf.proto == 0xffff) { - if (conf->proto == PC300_PROTO_MLPPP){ - /* ifdown interface */ - cpc_close(dev); - } - } else { - memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t)); - /* FIXME hdlc->proto.id = conf->proto; */ - } - } -#else - memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t)); - /* FIXME hdlc->proto.id = conf->proto; */ -#endif - return 0; - case SIOCGPC300STATUS: - cpc_sca_status(card, ch); - return 0; - case SIOCGPC300FALCSTATUS: - cpc_falc_status(card, ch); - return 0; - - case SIOCGPC300UTILSTATS: - { - if (!arg) { /* clear statistics */ - memset(hdlc_stats(dev), 0, sizeof(struct net_device_stats)); - if (card->hw.type == PC300_TE) { - memset(&chan->falc, 0, sizeof(falc_t)); - } - } else { - pc300stats_t pc300stats; - - memset(&pc300stats, 0, sizeof(pc300stats_t)); - 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(dev), - sizeof(struct net_device_stats)); - if (card->hw.type == PC300_TE) - memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t)); - if (copy_to_user(arg, &pc300stats, sizeof(pc300stats_t))) - return -EFAULT; - } - return 0; - } - - case SIOCGPC300UTILSTATUS: - { - struct pc300status pc300status; - - pc300status.hw_type = card->hw.type; - if (card->hw.type == PC300_TE) { - pc300status.te_status.sync = chan->falc.sync; - pc300status.te_status.red_alarm = chan->falc.red_alarm; - pc300status.te_status.blue_alarm = chan->falc.blue_alarm; - pc300status.te_status.loss_fa = chan->falc.loss_fa; - pc300status.te_status.yellow_alarm =chan->falc.yellow_alarm; - pc300status.te_status.loss_mfa = chan->falc.loss_mfa; - pc300status.te_status.prbs = chan->falc.prbs; - } else { - pc300status.gen_status.dcd = - !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_DCD); - pc300status.gen_status.cts = - !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_CTS); - pc300status.gen_status.rts = - !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_RTS); - pc300status.gen_status.dtr = - !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_DTR); - /* There is no DSR in HD64572 */ - } - if (!arg - || copy_to_user(arg, &pc300status, sizeof(pc300status_t))) - return -EINVAL; - return 0; - } - - case SIOCSPC300TRACE: - /* Sets/resets a trace_flag for the respective device */ - if (!arg || copy_from_user(&d->trace_on, arg,sizeof(unsigned char))) - return -EINVAL; - return 0; - - case SIOCSPC300LOOPBACK: - { - struct pc300loopback pc300loop; - - /* TE boards only */ - if (card->hw.type != PC300_TE) - return -EINVAL; - - if (!arg || - copy_from_user(&pc300loop, arg, sizeof(pc300loopback_t))) - return -EINVAL; - switch (pc300loop.loop_type) { - case PC300LOCLOOP: /* Turn the local loop on/off */ - falc_local_loop(card, ch, pc300loop.loop_on); - return 0; - - case PC300REMLOOP: /* Turn the remote loop on/off */ - falc_remote_loop(card, ch, pc300loop.loop_on); - return 0; - - case PC300PAYLOADLOOP: /* Turn the payload loop on/off */ - falc_payload_loop(card, ch, pc300loop.loop_on); - return 0; - - case PC300GENLOOPUP: /* Generate loop UP */ - if (pc300loop.loop_on) { - falc_generate_loop_up_code (card, ch); - } else { - turn_off_xlu(card, ch); - } - return 0; - - case PC300GENLOOPDOWN: /* Generate loop DOWN */ - if (pc300loop.loop_on) { - falc_generate_loop_down_code (card, ch); - } else { - turn_off_xld(card, ch); - } - return 0; - - default: - return -EINVAL; - } - } - - case SIOCSPC300PATTERNTEST: - /* Turn the pattern test on/off and show the errors counter */ - { - struct pc300patterntst pc300patrntst; - - /* TE boards only */ - if (card->hw.type != PC300_TE) - return -EINVAL; - - if (card->hw.cpld_id < 0x02) { - /* CPLD_ID < 0x02 doesn't support pattern test */ - return -EINVAL; - } - - if (!arg || - copy_from_user(&pc300patrntst,arg,sizeof(pc300patterntst_t))) - return -EINVAL; - if (pc300patrntst.patrntst_on == 2) { - if (chan->falc.prbs == 0) { - falc_pattern_test(card, ch, 1); - } - pc300patrntst.num_errors = - falc_pattern_test_error(card, ch); - if (!arg - || copy_to_user(arg, &pc300patrntst, - sizeof (pc300patterntst_t))) - return -EINVAL; - } else { - falc_pattern_test(card, ch, pc300patrntst.patrntst_on); - } - return 0; - } - - case SIOCWANDEV: - switch (ifr->ifr_settings.type) { - case IF_GET_IFACE: - { - const size_t size = sizeof(sync_serial_settings); - ifr->ifr_settings.type = conf->media; - if (ifr->ifr_settings.size < size) { - /* data size wanted */ - ifr->ifr_settings.size = size; - return -ENOBUFS; - } - - if (copy_to_user(settings->ifs_ifsu.sync, - &conf->phys_settings, size)) { - return -EFAULT; - } - return 0; - } - - case IF_IFACE_V35: - case IF_IFACE_V24: - case IF_IFACE_X21: - { - const size_t size = sizeof(sync_serial_settings); - - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - /* incorrect data len? */ - if (ifr->ifr_settings.size != size) { - return -ENOBUFS; - } - - if (copy_from_user(&conf->phys_settings, - settings->ifs_ifsu.sync, size)) { - return -EFAULT; - } - - if (conf->phys_settings.loopback) { - cpc_writeb(card->hw.scabase + M_REG(MD2, ch), - cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | - MD2_LOOP_MIR); - } - conf->media = ifr->ifr_settings.type; - return 0; - } - - case IF_IFACE_T1: - case IF_IFACE_E1: - { - const size_t te_size = sizeof(te1_settings); - const size_t size = sizeof(sync_serial_settings); - - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - - /* incorrect data len? */ - if (ifr->ifr_settings.size != te_size) { - return -ENOBUFS; - } - - if (copy_from_user(&conf->phys_settings, - settings->ifs_ifsu.te1, size)) { - return -EFAULT; - }/* Ignoring HDLC slot_map for a while */ - - if (conf->phys_settings.loopback) { - cpc_writeb(card->hw.scabase + M_REG(MD2, ch), - cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | - MD2_LOOP_MIR); - } - conf->media = ifr->ifr_settings.type; - return 0; - } - default: - return hdlc_ioctl(dev, ifr, cmd); - } - - default: - return hdlc_ioctl(dev, ifr, cmd); - } -} - -static struct net_device_stats *cpc_get_stats(struct net_device *dev) -{ - return hdlc_stats(dev); -} - -static int clock_rate_calc(uclong rate, uclong clock, int *br_io) -{ - int br, tc; - int br_pwr, error; - - *br_io = 0; - - if (rate == 0) - return (0); - - for (br = 0, br_pwr = 1; br <= 9; br++, br_pwr <<= 1) { - if ((tc = clock / br_pwr / rate) <= 0xff) { - *br_io = br; - break; - } - } - - if (tc <= 0xff) { - error = ((rate - (clock / br_pwr / rate)) / rate) * 1000; - /* Errors bigger than +/- 1% won't be tolerated */ - if (error < -10 || error > 10) - return (-1); - else - return (tc); - } else { - return (-1); - } -} - -static int ch_config(pc300dev_t * d) -{ - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - pc300_t *card = (pc300_t *) chan->card; - void __iomem *scabase = card->hw.scabase; - void __iomem *plxbase = card->hw.plxbase; - int ch = chan->channel; - uclong clkrate = chan->conf.phys_settings.clock_rate; - uclong clktype = chan->conf.phys_settings.clock_type; - ucshort encoding = chan->conf.proto_settings.encoding; - ucshort parity = chan->conf.proto_settings.parity; - ucchar md0, md2; - - /* Reset the channel */ - cpc_writeb(scabase + M_REG(CMD, ch), CMD_CH_RST); - - /* Configure the SCA registers */ - switch (parity) { - case PARITY_NONE: - md0 = MD0_BIT_SYNC; - break; - case PARITY_CRC16_PR0: - md0 = MD0_CRC16_0|MD0_CRCC0|MD0_BIT_SYNC; - break; - case PARITY_CRC16_PR1: - md0 = MD0_CRC16_1|MD0_CRCC0|MD0_BIT_SYNC; - break; - case PARITY_CRC32_PR1_CCITT: - md0 = MD0_CRC32|MD0_CRCC0|MD0_BIT_SYNC; - break; - case PARITY_CRC16_PR1_CCITT: - default: - md0 = MD0_CRC_CCITT|MD0_CRCC0|MD0_BIT_SYNC; - break; - } - switch (encoding) { - case ENCODING_NRZI: - md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZI; - break; - case ENCODING_FM_MARK: /* FM1 */ - md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM1; - break; - case ENCODING_FM_SPACE: /* FM0 */ - md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM0; - break; - case ENCODING_MANCHESTER: /* It's not working... */ - md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_MANCH; - break; - case ENCODING_NRZ: - default: - md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZ; - break; - } - cpc_writeb(scabase + M_REG(MD0, ch), md0); - cpc_writeb(scabase + M_REG(MD1, ch), 0); - cpc_writeb(scabase + M_REG(MD2, ch), md2); - cpc_writeb(scabase + M_REG(IDL, ch), 0x7e); - cpc_writeb(scabase + M_REG(CTL, ch), CTL_URSKP | CTL_IDLC); - - /* Configure HW media */ - switch (card->hw.type) { - case PC300_RSV: - if (conf->media == IF_IFACE_V35) { - cpc_writel((plxbase + card->hw.gpioc_reg), - cpc_readl(plxbase + card->hw.gpioc_reg) | PC300_CHMEDIA_MASK(ch)); - } else { - cpc_writel((plxbase + card->hw.gpioc_reg), - cpc_readl(plxbase + card->hw.gpioc_reg) & ~PC300_CHMEDIA_MASK(ch)); - } - break; - - case PC300_X21: - break; - - case PC300_TE: - te_config(card, ch); - break; - } - - switch (card->hw.type) { - 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)); - if (clktype == CLOCK_INT) { - cpc_writeb(scabase + M_REG(TMCR, ch), tmc); - cpc_writeb(scabase + M_REG(RXS, ch), - (RXS_IBRG | br)); - } else { - cpc_writeb(scabase + M_REG(TMCR, ch), 1); - cpc_writeb(scabase + M_REG(RXS, ch), 0); - } - if (card->hw.type == PC300_X21) { - cpc_writeb(scabase + M_REG(GPO, ch), 1); - cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1); - } else { - cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1); - } - } else { - cpc_writeb(scabase + M_REG(TMCT, ch), 1); - if (clktype == CLOCK_EXT) { - cpc_writeb(scabase + M_REG(TXS, ch), - TXS_DTRXC); - } else { - cpc_writeb(scabase + M_REG(TXS, ch), - TXS_DTRXC|TXS_RCLK); - } - cpc_writeb(scabase + M_REG(TMCR, ch), 1); - cpc_writeb(scabase + M_REG(RXS, ch), 0); - if (card->hw.type == PC300_X21) { - cpc_writeb(scabase + M_REG(GPO, ch), 0); - cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1); - } else { - cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1); - } - } - break; - - case PC300_TE: - /* SCA always receives clock from the FALC chip */ - cpc_writeb(scabase + M_REG(TMCT, ch), 1); - cpc_writeb(scabase + M_REG(TXS, ch), 0); - cpc_writeb(scabase + M_REG(TMCR, ch), 1); - cpc_writeb(scabase + M_REG(RXS, ch), 0); - cpc_writeb(scabase + M_REG(EXS, ch), 0); - break; - } - - /* Enable Interrupts */ - cpc_writel(scabase + IER0, - cpc_readl(scabase + IER0) | - IR0_M(IR0_RXINTA, ch) | - IR0_DRX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch) | - IR0_DTX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch)); - cpc_writeb(scabase + M_REG(IE0, ch), - cpc_readl(scabase + M_REG(IE0, ch)) | IE0_RXINTA); - cpc_writeb(scabase + M_REG(IE1, ch), - cpc_readl(scabase + M_REG(IE1, ch)) | IE1_CDCD); - - return 0; -} - -static int rx_config(pc300dev_t * d) -{ - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - void __iomem *scabase = card->hw.scabase; - int ch = chan->channel; - - cpc_writeb(scabase + DSR_RX(ch), 0); - - /* General RX settings */ - cpc_writeb(scabase + M_REG(RRC, ch), 0); - cpc_writeb(scabase + M_REG(RNR, ch), 16); - - /* Enable reception */ - cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT); - cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_ENA); - - /* Initialize DMA stuff */ - chan->rx_first_bd = 0; - chan->rx_last_bd = N_DMA_RX_BUF - 1; - rx_dma_buf_init(card, ch); - cpc_writeb(scabase + DCR_RX(ch), DCR_FCT_CLR); - cpc_writeb(scabase + DMR_RX(ch), (DMR_TMOD | DMR_NF)); - cpc_writeb(scabase + DIR_RX(ch), (DIR_EOM | DIR_BOF)); - - /* Start DMA */ - rx_dma_start(card, ch); - - return 0; -} - -static int tx_config(pc300dev_t * d) -{ - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - void __iomem *scabase = card->hw.scabase; - int ch = chan->channel; - - cpc_writeb(scabase + DSR_TX(ch), 0); - - /* General TX settings */ - cpc_writeb(scabase + M_REG(TRC0, ch), 0); - cpc_writeb(scabase + M_REG(TFS, ch), 32); - cpc_writeb(scabase + M_REG(TNR0, ch), 20); - cpc_writeb(scabase + M_REG(TNR1, ch), 48); - cpc_writeb(scabase + M_REG(TCR, ch), 8); - - /* Enable transmission */ - cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT); - - /* Initialize DMA stuff */ - chan->tx_first_bd = 0; - chan->tx_next_bd = 0; - tx_dma_buf_init(card, ch); - cpc_writeb(scabase + DCR_TX(ch), DCR_FCT_CLR); - cpc_writeb(scabase + DMR_TX(ch), (DMR_TMOD | DMR_NF)); - cpc_writeb(scabase + DIR_TX(ch), (DIR_EOM | DIR_BOF | DIR_UDRF)); - cpc_writel(scabase + DTX_REG(CDAL, ch), TX_BD_ADDR(ch, chan->tx_first_bd)); - cpc_writel(scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd)); - - return 0; -} - -static int cpc_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ - pc300dev_t *d = (pc300dev_t *)dev->priv; - pc300ch_t *chan = (pc300ch_t *)d->chan; - pc300_t *card = (pc300_t *)chan->card; - pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; - - if (card->hw.type == PC300_TE) { - if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI) { - return -EINVAL; - } - } else { - if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI && - encoding != ENCODING_FM_MARK && encoding != ENCODING_FM_SPACE) { - /* Driver doesn't support ENCODING_MANCHESTER yet */ - return -EINVAL; - } - } - - if (parity != PARITY_NONE && parity != PARITY_CRC16_PR0 && - parity != PARITY_CRC16_PR1 && parity != PARITY_CRC32_PR1_CCITT && - parity != PARITY_CRC16_PR1_CCITT) { - return -EINVAL; - } - - conf->proto_settings.encoding = encoding; - conf->proto_settings.parity = parity; - return 0; -} - -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, rc; - void __iomem *scabase = card->hw.scabase; - - rc = ch_config(d); - if (rc) - return rc; - - rx_config(d); - - tx_config(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) -{ - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - falc_t *pfalc = (falc_t *) & chan->falc; - int ch = chan->channel; - - cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_CH_RST); - rx_dma_stop(card, ch); - tx_dma_stop(card, ch); - - if (card->hw.type == PC300_TE) { - memset(pfalc, 0, sizeof(falc_t)); - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & - ~((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK | - CPLD_REG2_FALC_LED2) << (2 * ch))); - /* Reset the FALC chip */ - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) | - (CPLD_REG1_FALC_RESET << (2 * ch))); - udelay(10000); - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) & - ~(CPLD_REG1_FALC_RESET << (2 * ch))); - } -} - -int cpc_open(struct net_device *dev) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - struct ifreq ifr; - int result; - -#ifdef PC300_DEBUG_OTHER - 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 (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) { - dev->priv = d; - } - if (result) { - return result; - } - - sprintf(ifr.ifr_name, "%s", dev->name); - 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) -{ - pc300dev_t *d = (pc300dev_t *) dev->priv; - pc300ch_t *chan = (pc300ch_t *) d->chan; - pc300_t *card = (pc300_t *) chan->card; - unsigned long flags; - -#ifdef PC300_DEBUG_OTHER - printk("pc300: cpc_close"); -#endif - - netif_stop_queue(dev); - - CPC_LOCK(card, flags); - cpc_closech(d); - CPC_UNLOCK(card, flags); - - hdlc_close(dev); - if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) { - d->if_ptr = NULL; - } -#ifdef CONFIG_PC300_MLPPP - if (chan->conf.proto == PC300_PROTO_MLPPP) { - cpc_tty_unregister_service(d); - chan->conf.proto = 0xffff; - } -#endif - - return 0; -} - -static uclong detect_ram(pc300_t * card) -{ - uclong i; - ucchar data; - void __iomem *rambase = card->hw.rambase; - - card->hw.ramsize = PC300_RAMSIZE; - /* Let's find out how much RAM is present on this board */ - for (i = 0; i < card->hw.ramsize; i++) { - data = (ucchar) (i & 0xff); - cpc_writeb(rambase + i, data); - if (cpc_readb(rambase + i) != data) { - break; - } - } - return (i); -} - -static void plx_init(pc300_t * card) -{ - struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase; - - /* Reset PLX */ - cpc_writel(&plx_ctl->init_ctrl, - cpc_readl(&plx_ctl->init_ctrl) | 0x40000000); - udelay(10000L); - cpc_writel(&plx_ctl->init_ctrl, - cpc_readl(&plx_ctl->init_ctrl) & ~0x40000000); - - /* Reload Config. Registers from EEPROM */ - cpc_writel(&plx_ctl->init_ctrl, - cpc_readl(&plx_ctl->init_ctrl) | 0x20000000); - udelay(10000L); - cpc_writel(&plx_ctl->init_ctrl, - cpc_readl(&plx_ctl->init_ctrl) & ~0x20000000); - -} - -static inline void show_version(void) -{ - char *rcsvers, *rcsdate, *tmp; - - rcsvers = strchr(rcsid, ' '); - rcsvers++; - tmp = strchr(rcsvers, ' '); - *tmp++ = '\0'; - rcsdate = strchr(tmp, ' '); - rcsdate++; - tmp = strrchr(rcsdate, ' '); - *tmp = '\0'; - printk(KERN_INFO "Cyclades-PC300 driver %s %s (built %s %s)\n", - rcsvers, rcsdate, __DATE__, __TIME__); -} /* show_version */ - -static void cpc_init_card(pc300_t * card) -{ - int i, devcount = 0; - static int board_nbr = 1; - - /* Enable interrupts on the PCI bridge */ - plx_init(card); - cpc_writew(card->hw.plxbase + card->hw.intctl_reg, - cpc_readw(card->hw.plxbase + card->hw.intctl_reg) | 0x0040); - -#ifdef USE_PCI_CLOCK - /* Set board clock to PCI clock */ - cpc_writel(card->hw.plxbase + card->hw.gpioc_reg, - cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) | 0x00000004UL); - card->hw.clock = PC300_PCI_CLOCK; -#else - /* Set board clock to internal oscillator clock */ - cpc_writel(card->hw.plxbase + card->hw.gpioc_reg, - cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & ~0x00000004UL); - card->hw.clock = PC300_OSC_CLOCK; -#endif - - /* Detect actual on-board RAM size */ - card->hw.ramsize = detect_ram(card); - - /* Set Global SCA-II registers */ - cpc_writeb(card->hw.scabase + PCR, PCR_PR2); - cpc_writeb(card->hw.scabase + BTCR, 0x10); - cpc_writeb(card->hw.scabase + WCRL, 0); - cpc_writeb(card->hw.scabase + DMER, 0x80); - - if (card->hw.type == PC300_TE) { - ucchar reg1; - - /* Check CPLD version */ - reg1 = cpc_readb(card->hw.falcbase + CPLD_REG1); - cpc_writeb(card->hw.falcbase + CPLD_REG1, (reg1 + 0x5a)); - if (cpc_readb(card->hw.falcbase + CPLD_REG1) == reg1) { - /* New CPLD */ - card->hw.cpld_id = cpc_readb(card->hw.falcbase + CPLD_ID_REG); - card->hw.cpld_reg1 = CPLD_V2_REG1; - card->hw.cpld_reg2 = CPLD_V2_REG2; - } else { - /* old CPLD */ - card->hw.cpld_id = 0; - card->hw.cpld_reg1 = CPLD_REG1; - card->hw.cpld_reg2 = CPLD_REG2; - cpc_writeb(card->hw.falcbase + CPLD_REG1, reg1); - } - - /* Enable the board's global clock */ - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) | - CPLD_REG1_GLOBAL_CLK); - - } - - for (i = 0; i < card->hw.nchan; i++) { - pc300ch_t *chan = &card->chan[i]; - pc300dev_t *d = &chan->d; - hdlc_device *hdlc; - struct net_device *dev; - - chan->card = card; - chan->channel = i; - chan->conf.phys_settings.clock_rate = 0; - chan->conf.phys_settings.clock_type = CLOCK_EXT; - chan->conf.proto_settings.encoding = ENCODING_NRZ; - chan->conf.proto_settings.parity = PARITY_CRC16_PR1_CCITT; - switch (card->hw.type) { - case PC300_TE: - chan->conf.media = IF_IFACE_T1; - chan->conf.lcode = PC300_LC_B8ZS; - chan->conf.fr_mode = PC300_FR_ESF; - chan->conf.lbo = PC300_LBO_0_DB; - chan->conf.rx_sens = PC300_RX_SENS_SH; - chan->conf.tslot_bitmap = 0xffffffffUL; - break; - - case PC300_X21: - chan->conf.media = IF_IFACE_X21; - break; - - case PC300_RSV: - default: - chan->conf.media = IF_IFACE_V35; - break; - } - chan->conf.proto = IF_PROTO_PPP; - chan->tx_first_bd = 0; - chan->tx_next_bd = 0; - chan->rx_first_bd = 0; - chan->rx_last_bd = N_DMA_RX_BUF - 1; - chan->nfree_tx_bd = N_DMA_TX_BUF; - - d->chan = chan; - d->tx_skb = NULL; - d->trace_on = 0; - d->line_on = 0; - d->line_off = 0; - - dev = alloc_hdlcdev(NULL); - if (dev == NULL) - continue; - - hdlc = dev_to_hdlc(dev); - hdlc->xmit = cpc_queue_xmit; - hdlc->attach = cpc_attach; - d->dev = dev; - dev->mem_start = card->hw.ramphys; - dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1; - dev->irq = card->hw.irq; - dev->init = NULL; - dev->tx_queue_len = PC300_TX_QUEUE_LEN; - dev->mtu = PC300_DEF_MTU; - - dev->open = cpc_open; - dev->stop = cpc_close; - dev->tx_timeout = cpc_tx_timeout; - dev->watchdog_timeo = PC300_TX_TIMEOUT; - dev->get_stats = cpc_get_stats; - dev->set_multicast_list = NULL; - dev->set_mac_address = NULL; - dev->change_mtu = cpc_change_mtu; - dev->do_ioctl = cpc_ioctl; - - if (register_hdlc_device(dev) == 0) { - dev->priv = d; /* We need 'priv', hdlc doesn't */ - printk("%s: Cyclades-PC300/", dev->name); - switch (card->hw.type) { - case PC300_TE: - if (card->hw.bus == PC300_PMC) { - printk("TE-M"); - } else { - printk("TE "); - } - break; - - case PC300_X21: - printk("X21 "); - break; - - case PC300_RSV: - default: - printk("RSV "); - break; - } - printk (" #%d, %dKB of RAM at 0x%08x, IRQ%d, channel %d.\n", - board_nbr, card->hw.ramsize / 1024, - card->hw.ramphys, card->hw.irq, i + 1); - devcount++; - } else { - printk ("Dev%d on card(0x%08x): unable to allocate i/f name.\n", - i + 1, card->hw.ramphys); - free_netdev(dev); - continue; - } - } - spin_lock_init(&card->card_lock); - - board_nbr++; -} - -static int __devinit -cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int first_time = 1; - int err, eeprom_outdated = 0; - ucshort device_id; - pc300_t *card; - - if (first_time) { - first_time = 0; - show_version(); -#ifdef CONFIG_PC300_MLPPP - cpc_tty_reset_var(); -#endif - } - - if ((err = pci_enable_device(pdev)) < 0) - return err; - - card = kzalloc(sizeof(pc300_t), GFP_KERNEL); - if (card == NULL) { - printk("PC300 found at RAM 0x%016llx, " - "but could not allocate card structure.\n", - (unsigned long long)pci_resource_start(pdev, 3)); - err = -ENOMEM; - goto err_disable_dev; - } - - err = -ENODEV; - - /* read PCI configuration area */ - device_id = ent->device; - card->hw.irq = pdev->irq; - card->hw.iophys = pci_resource_start(pdev, 1); - card->hw.iosize = pci_resource_len(pdev, 1); - card->hw.scaphys = pci_resource_start(pdev, 2); - card->hw.scasize = pci_resource_len(pdev, 2); - card->hw.ramphys = pci_resource_start(pdev, 3); - card->hw.alloc_ramsize = pci_resource_len(pdev, 3); - card->hw.falcphys = pci_resource_start(pdev, 4); - card->hw.falcsize = pci_resource_len(pdev, 4); - card->hw.plxphys = pci_resource_start(pdev, 5); - card->hw.plxsize = pci_resource_len(pdev, 5); - - switch (device_id) { - case PCI_DEVICE_ID_PC300_RX_1: - case PCI_DEVICE_ID_PC300_TE_1: - case PCI_DEVICE_ID_PC300_TE_M_1: - card->hw.nchan = 1; - break; - - case PCI_DEVICE_ID_PC300_RX_2: - case PCI_DEVICE_ID_PC300_TE_2: - case PCI_DEVICE_ID_PC300_TE_M_2: - default: - card->hw.nchan = PC300_MAXCHAN; - break; - } -#ifdef PC300_DEBUG_PCI - printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq); - printk("cpc:found ramaddr=0x%08lx plxaddr=0x%08lx " - "ctladdr=0x%08lx falcaddr=0x%08lx\n", - card->hw.ramphys, card->hw.plxphys, card->hw.scaphys, - card->hw.falcphys); -#endif - /* Although we don't use this I/O region, we should - * request it from the kernel anyway, to avoid problems - * with other drivers accessing it. */ - if (!request_region(card->hw.iophys, card->hw.iosize, "PLX Registers")) { - /* In case we can't allocate it, warn user */ - printk("WARNING: couldn't allocate I/O region for PC300 board " - "at 0x%08x!\n", card->hw.ramphys); - } - - if (card->hw.plxphys) { - pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, card->hw.plxphys); - } else { - eeprom_outdated = 1; - card->hw.plxphys = pci_resource_start(pdev, 0); - card->hw.plxsize = pci_resource_len(pdev, 0); - } - - if (!request_mem_region(card->hw.plxphys, card->hw.plxsize, - "PLX Registers")) { - printk("PC300 found at RAM 0x%08x, " - "but could not allocate PLX mem region.\n", - card->hw.ramphys); - goto err_release_io; - } - if (!request_mem_region(card->hw.ramphys, card->hw.alloc_ramsize, - "On-board RAM")) { - printk("PC300 found at RAM 0x%08x, " - "but could not allocate RAM mem region.\n", - card->hw.ramphys); - goto err_release_plx; - } - if (!request_mem_region(card->hw.scaphys, card->hw.scasize, - "SCA-II Registers")) { - printk("PC300 found at RAM 0x%08x, " - "but could not allocate SCA mem region.\n", - card->hw.ramphys); - goto err_release_ram; - } - - card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize); - card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize); - card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize); - switch (device_id) { - case PCI_DEVICE_ID_PC300_TE_1: - case PCI_DEVICE_ID_PC300_TE_2: - case PCI_DEVICE_ID_PC300_TE_M_1: - case PCI_DEVICE_ID_PC300_TE_M_2: - request_mem_region(card->hw.falcphys, card->hw.falcsize, - "FALC Registers"); - card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize); - break; - - case PCI_DEVICE_ID_PC300_RX_1: - case PCI_DEVICE_ID_PC300_RX_2: - default: - card->hw.falcbase = NULL; - break; - } - -#ifdef PC300_DEBUG_PCI - printk("cpc: relocate ramaddr=0x%08lx plxaddr=0x%08lx " - "ctladdr=0x%08lx falcaddr=0x%08lx\n", - card->hw.rambase, card->hw.plxbase, card->hw.scabase, - card->hw.falcbase); -#endif - - /* Set PCI drv pointer to the card structure */ - pci_set_drvdata(pdev, card); - - /* Set board type */ - switch (device_id) { - case PCI_DEVICE_ID_PC300_TE_1: - case PCI_DEVICE_ID_PC300_TE_2: - case PCI_DEVICE_ID_PC300_TE_M_1: - case PCI_DEVICE_ID_PC300_TE_M_2: - card->hw.type = PC300_TE; - - if ((device_id == PCI_DEVICE_ID_PC300_TE_M_1) || - (device_id == PCI_DEVICE_ID_PC300_TE_M_2)) { - card->hw.bus = PC300_PMC; - /* Set PLX register offsets */ - card->hw.gpioc_reg = 0x54; - card->hw.intctl_reg = 0x4c; - } else { - card->hw.bus = PC300_PCI; - /* Set PLX register offsets */ - card->hw.gpioc_reg = 0x50; - card->hw.intctl_reg = 0x4c; - } - break; - - case PCI_DEVICE_ID_PC300_RX_1: - case PCI_DEVICE_ID_PC300_RX_2: - default: - card->hw.bus = PC300_PCI; - /* Set PLX register offsets */ - card->hw.gpioc_reg = 0x50; - card->hw.intctl_reg = 0x4c; - - if ((cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & PC300_CTYPE_MASK)) { - card->hw.type = PC300_X21; - } else { - card->hw.type = PC300_RSV; - } - break; - } - - /* Allocate IRQ */ - if (request_irq(card->hw.irq, cpc_intr, IRQF_SHARED, "Cyclades-PC300", card)) { - printk ("PC300 found at RAM 0x%08x, but could not allocate IRQ%d.\n", - card->hw.ramphys, card->hw.irq); - goto err_io_unmap; - } - - cpc_init_card(card); - - if (eeprom_outdated) - printk("WARNING: PC300 with outdated EEPROM.\n"); - return 0; - -err_io_unmap: - iounmap(card->hw.plxbase); - iounmap(card->hw.scabase); - iounmap(card->hw.rambase); - if (card->hw.type == PC300_TE) { - iounmap(card->hw.falcbase); - release_mem_region(card->hw.falcphys, card->hw.falcsize); - } - release_mem_region(card->hw.scaphys, card->hw.scasize); -err_release_ram: - release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize); -err_release_plx: - release_mem_region(card->hw.plxphys, card->hw.plxsize); -err_release_io: - release_region(card->hw.iophys, card->hw.iosize); - kfree(card); -err_disable_dev: - pci_disable_device(pdev); - return err; -} - -static void __devexit cpc_remove_one(struct pci_dev *pdev) -{ - pc300_t *card = pci_get_drvdata(pdev); - - if (card->hw.rambase) { - int i; - - /* Disable interrupts on the PCI bridge */ - cpc_writew(card->hw.plxbase + card->hw.intctl_reg, - cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040)); - - for (i = 0; i < card->hw.nchan; i++) { - unregister_hdlc_device(card->chan[i].d.dev); - } - iounmap(card->hw.plxbase); - iounmap(card->hw.scabase); - iounmap(card->hw.rambase); - release_mem_region(card->hw.plxphys, card->hw.plxsize); - release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize); - release_mem_region(card->hw.scaphys, card->hw.scasize); - release_region(card->hw.iophys, card->hw.iosize); - if (card->hw.type == PC300_TE) { - iounmap(card->hw.falcbase); - release_mem_region(card->hw.falcphys, card->hw.falcsize); - } - for (i = 0; i < card->hw.nchan; i++) - if (card->chan[i].d.dev) - free_netdev(card->chan[i].d.dev); - if (card->hw.irq) - free_irq(card->hw.irq, card); - kfree(card); - pci_disable_device(pdev); - } -} - -static struct pci_driver cpc_driver = { - .name = "pc300", - .id_table = cpc_pci_dev_id, - .probe = cpc_init_one, - .remove = __devexit_p(cpc_remove_one), -}; - -static int __init cpc_init(void) -{ - return pci_register_driver(&cpc_driver); -} - -static void __exit cpc_cleanup_module(void) -{ - pci_unregister_driver(&cpc_driver); -} - -module_init(cpc_init); -module_exit(cpc_cleanup_module); - -MODULE_DESCRIPTION("Cyclades-PC300 cards driver"); -MODULE_AUTHOR( "Author: Ivan Passos <ivan@cyclades.com>\r\n" - "Maintainer: PC300 Maintainer <pc300@cyclades.com"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c deleted file mode 100644 index 63abfd72542..00000000000 --- a/drivers/net/wan/pc300_tty.c +++ /dev/null @@ -1,1092 +0,0 @@ -/* - * pc300_tty.c Cyclades-PC300(tm) TTY Driver. - * - * Author: Regina Kodato <reginak@cyclades.com> - * - * Copyright: (c) 1999-2002 Cyclades Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * $Log: pc300_tty.c,v $ - * Revision 3.7 2002/03/07 14:17:09 henrique - * License data fixed - * - * Revision 3.6 2001/12/10 12:29:42 regina - * Fix the MLPPP bug - * - * Revision 3.5 2001/10/31 11:20:05 regina - * automatic pppd starts - * - * Revision 3.4 2001/08/06 12:01:51 regina - * problem in DSR_DE bit - * - * Revision 3.3 2001/07/26 22:58:41 regina - * update EDA value - * - * Revision 3.2 2001/07/12 13:11:20 regina - * bug fix - DCD-OFF in pc300 tty driver - * - * DMA transmission bug fix - * - * Revision 3.1 2001/06/22 13:13:02 regina - * MLPPP implementation - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/if.h> -#include <linux/skbuff.h> -/* TTY includes */ -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - -#include "pc300.h" - -/* defines and macros */ -/* TTY Global definitions */ -#define CPC_TTY_NPORTS 8 /* maximum number of the sync tty connections */ -#define CPC_TTY_MAJOR CYCLADES_MAJOR -#define CPC_TTY_MINOR_START 240 /* minor of the first PC300 interface */ - -#define CPC_TTY_MAX_MTU 2000 - -/* tty interface state */ -#define CPC_TTY_ST_IDLE 0 -#define CPC_TTY_ST_INIT 1 /* configured with MLPPP and up */ -#define CPC_TTY_ST_OPEN 2 /* opened by application */ - -#define CPC_TTY_LOCK(card,flags)\ - do {\ - spin_lock_irqsave(&card->card_lock, flags); \ - } while (0) - -#define CPC_TTY_UNLOCK(card,flags) \ - do {\ - spin_unlock_irqrestore(&card->card_lock, flags); \ - } while (0) - -//#define CPC_TTY_DBG(format,a...) printk(format,##a) -#define CPC_TTY_DBG(format,a...) - -/* data structures */ -typedef struct _st_cpc_rx_buf { - struct _st_cpc_rx_buf *next; - int size; - unsigned char data[1]; -} st_cpc_rx_buf; - -struct st_cpc_rx_list { - st_cpc_rx_buf *first; - st_cpc_rx_buf *last; -}; - -typedef struct _st_cpc_tty_area { - int state; /* state of the TTY interface */ - int num_open; - unsigned int tty_minor; /* minor this interface */ - volatile struct st_cpc_rx_list buf_rx; /* ptr. to reception buffer */ - unsigned char* buf_tx; /* ptr. to transmission buffer */ - pc300dev_t* pc300dev; /* ptr. to info struct in PC300 driver */ - unsigned char name[20]; /* interf. name + "-tty" */ - struct tty_struct *tty; - struct work_struct tty_tx_work; /* tx work - tx interrupt */ - struct work_struct tty_rx_work; /* rx work - rx interrupt */ - } st_cpc_tty_area; - -/* TTY data structures */ -static struct tty_driver serial_drv; - -/* local variables */ -static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS]; - -static int cpc_tty_cnt = 0; /* number of intrfaces configured with MLPPP */ -static int cpc_tty_unreg_flag = 0; - -/* TTY functions prototype */ -static int cpc_tty_open(struct tty_struct *tty, struct file *flip); -static void cpc_tty_close(struct tty_struct *tty, struct file *flip); -static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count); -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(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); -static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char); - -static int pc300_tiocmset(struct tty_struct *, struct file *, - unsigned int, unsigned int); -static int pc300_tiocmget(struct tty_struct *, struct file *); - -/* functions called by PC300 driver */ -void cpc_tty_init(pc300dev_t *dev); -void cpc_tty_unregister_service(pc300dev_t *pc300dev); -void cpc_tty_receive(pc300dev_t *pc300dev); -void cpc_tty_trigger_poll(pc300dev_t *pc300dev); -void cpc_tty_reset_var(void); - -/* - * PC300 TTY clear "signal" - */ -static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char signal) -{ - pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; - pc300_t *card = (pc300_t *) pc300chan->card; - int ch = pc300chan->channel; - unsigned long flags; - - CPC_TTY_DBG("%s-tty: Clear signal %x\n", - pc300dev->dev->name, signal); - CPC_TTY_LOCK(card, flags); - cpc_writeb(card->hw.scabase + M_REG(CTL,ch), - cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal); - CPC_TTY_UNLOCK(card,flags); -} - -/* - * PC300 TTY set "signal" to ON - */ -static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal) -{ - pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; - pc300_t *card = (pc300_t *) pc300chan->card; - int ch = pc300chan->channel; - unsigned long flags; - - CPC_TTY_DBG("%s-tty: Set signal %x\n", - pc300dev->dev->name, signal); - CPC_TTY_LOCK(card, flags); - cpc_writeb(card->hw.scabase + M_REG(CTL,ch), - cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal); - CPC_TTY_UNLOCK(card,flags); -} - -/* - * PC300 TTY initialization routine - * - * This routine is called by the PC300 driver during board configuration - * (ioctl=SIOCSP300CONF). At this point the adapter is completely - * initialized. - * o verify kernel version (only 2.4.x) - * o register TTY driver - * o init cpc_tty_area struct - */ -void cpc_tty_init(pc300dev_t *pc300dev) -{ - unsigned long port; - int aux; - st_cpc_tty_area * cpc_tty; - - /* hdlcX - X=interface number */ - port = pc300dev->dev->name[4] - '0'; - if (port >= CPC_TTY_NPORTS) { - printk("%s-tty: invalid interface selected (0-%i): %li", - pc300dev->dev->name, - CPC_TTY_NPORTS-1,port); - return; - } - - if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */ - CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n", - pc300dev->dev->name, - CPC_TTY_MAJOR, CPC_TTY_MINOR_START, - CPC_TTY_MINOR_START+CPC_TTY_NPORTS); - /* initialize tty driver struct */ - memset(&serial_drv,0,sizeof(struct tty_driver)); - serial_drv.magic = TTY_DRIVER_MAGIC; - serial_drv.owner = THIS_MODULE; - serial_drv.driver_name = "pc300_tty"; - serial_drv.name = "ttyCP"; - serial_drv.major = CPC_TTY_MAJOR; - serial_drv.minor_start = CPC_TTY_MINOR_START; - serial_drv.num = CPC_TTY_NPORTS; - serial_drv.type = TTY_DRIVER_TYPE_SERIAL; - serial_drv.subtype = SERIAL_TYPE_NORMAL; - - serial_drv.init_termios = tty_std_termios; - serial_drv.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; - serial_drv.flags = TTY_DRIVER_REAL_RAW; - - /* interface routines from the upper tty layer to the tty driver */ - serial_drv.open = cpc_tty_open; - serial_drv.close = cpc_tty_close; - serial_drv.write = cpc_tty_write; - serial_drv.write_room = cpc_tty_write_room; - serial_drv.chars_in_buffer = cpc_tty_chars_in_buffer; - serial_drv.tiocmset = pc300_tiocmset; - serial_drv.tiocmget = pc300_tiocmget; - serial_drv.flush_buffer = cpc_tty_flush_buffer; - serial_drv.hangup = cpc_tty_hangup; - - /* register the TTY driver */ - if (tty_register_driver(&serial_drv)) { - printk("%s-tty: Failed to register serial driver! ", - pc300dev->dev->name); - return; - } - - memset((void *)cpc_tty_area, 0, - sizeof(st_cpc_tty_area) * CPC_TTY_NPORTS); - } - - cpc_tty = &cpc_tty_area[port]; - - if (cpc_tty->state != CPC_TTY_ST_IDLE) { - CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n", - pc300dev->dev->name, port); - return; - } - - cpc_tty_cnt++; - cpc_tty->state = CPC_TTY_ST_INIT; - cpc_tty->num_open= 0; - cpc_tty->tty_minor = port + CPC_TTY_MINOR_START; - cpc_tty->pc300dev = pc300dev; - - 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; - - pc300dev->cpc_tty = (void *)cpc_tty; - - aux = strlen(pc300dev->dev->name); - memcpy(cpc_tty->name, pc300dev->dev->name, aux); - memcpy(&cpc_tty->name[aux], "-tty", 5); - - cpc_open(pc300dev->dev); - cpc_tty_signal_off(pc300dev, CTL_DTR); - - CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n", - cpc_tty->name,CPC_TTY_MAJOR,cpc_tty->tty_minor); - return; -} - -/* - * PC300 TTY OPEN routine - * - * This routine is called by the tty driver to open the interface - * o verify minor - * o allocate buffer to Rx and Tx - */ -static int cpc_tty_open(struct tty_struct *tty, struct file *flip) -{ - int port ; - st_cpc_tty_area *cpc_tty; - - if (!tty) { - return -ENODEV; - } - - port = tty->index; - - if ((port < 0) || (port >= CPC_TTY_NPORTS)){ - CPC_TTY_DBG("pc300_tty: open invalid port %d\n", port); - return -ENODEV; - } - - cpc_tty = &cpc_tty_area[port]; - - if (cpc_tty->state == CPC_TTY_ST_IDLE){ - CPC_TTY_DBG("%s: open - invalid interface, port=%d\n", - cpc_tty->name, tty->index); - return -ENODEV; - } - - if (cpc_tty->num_open == 0) { /* first open of this tty */ - if (!cpc_tty_area[port].buf_tx){ - cpc_tty_area[port].buf_tx = kmalloc(CPC_TTY_MAX_MTU,GFP_KERNEL); - if (!cpc_tty_area[port].buf_tx) { - CPC_TTY_DBG("%s: error in memory allocation\n",cpc_tty->name); - return -ENOMEM; - } - } - - if (cpc_tty_area[port].buf_rx.first) { - unsigned char * aux; - while (cpc_tty_area[port].buf_rx.first) { - aux = (unsigned char *)cpc_tty_area[port].buf_rx.first; - cpc_tty_area[port].buf_rx.first = cpc_tty_area[port].buf_rx.first->next; - kfree(aux); - } - cpc_tty_area[port].buf_rx.first = NULL; - cpc_tty_area[port].buf_rx.last = NULL; - } - - cpc_tty_area[port].state = CPC_TTY_ST_OPEN; - cpc_tty_area[port].tty = tty; - tty->driver_data = &cpc_tty_area[port]; - - cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR); - } - - cpc_tty->num_open++; - - CPC_TTY_DBG("%s: opening TTY driver\n", cpc_tty->name); - - /* avisar driver PC300 */ - return 0; -} - -/* - * PC300 TTY CLOSE routine - * - * This routine is called by the tty driver to close the interface - * o call close channel in PC300 driver (cpc_closech) - * o free Rx and Tx buffers - */ - -static void cpc_tty_close(struct tty_struct *tty, struct file *flip) -{ - st_cpc_tty_area *cpc_tty; - unsigned long flags; - int res; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlx-tty: no TTY in close \n"); - return; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty)|| (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); - return; - } - - if (!cpc_tty->num_open) { - CPC_TTY_DBG("%s: TTY is closed\n",cpc_tty->name); - return; - } - - if (--cpc_tty->num_open > 0) { - CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name); - return; - } - - cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR); - - CPC_TTY_LOCK(cpc_tty->pc300dev->chan->card, flags); /* lock irq */ - cpc_tty->tty = NULL; - cpc_tty->state = CPC_TTY_ST_INIT; - CPC_TTY_UNLOCK(cpc_tty->pc300dev->chan->card, flags); /* unlock irq */ - - if (cpc_tty->buf_rx.first) { - unsigned char * aux; - while (cpc_tty->buf_rx.first) { - aux = (unsigned char *)cpc_tty->buf_rx.first; - cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; - kfree(aux); - } - cpc_tty->buf_rx.first = NULL; - cpc_tty->buf_rx.last = NULL; - } - - kfree(cpc_tty->buf_tx); - cpc_tty->buf_tx = NULL; - - CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name); - - if (!serial_drv.refcount && cpc_tty_unreg_flag) { - cpc_tty_unreg_flag = 0; - CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name); - if ((res=tty_unregister_driver(&serial_drv))) { - CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n", - cpc_tty->name,res); - } - } - return; -} - -/* - * PC300 TTY WRITE routine - * - * This routine is called by the tty driver to write a series of characters - * to the tty device. The characters may come from user or kernel space. - * o verify the DCD signal - * o send characters to board and start the transmission - */ -static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - st_cpc_tty_area *cpc_tty; - pc300ch_t *pc300chan; - pc300_t *card; - int ch; - unsigned long flags; - struct net_device_stats *stats; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY in write\n"); - return -ENODEV; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n", cpc_tty->name); - return -ENODEV; - } - - if (count > CPC_TTY_MAX_MTU) { - CPC_TTY_DBG("%s: count is invalid\n",cpc_tty->name); - return -EINVAL; /* frame too big */ - } - - CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count); - - pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; - stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev); - card = (pc300_t *) pc300chan->card; - ch = pc300chan->channel; - - /* verify DCD signal*/ - if (cpc_readb(card->hw.scabase + M_REG(ST3,ch)) & ST3_DCD) { - /* DCD is OFF */ - CPC_TTY_DBG("%s : DCD is OFF\n", cpc_tty->name); - stats->tx_errors++; - stats->tx_carrier_errors++; - CPC_TTY_LOCK(card, flags); - cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); - - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & - ~(CPLD_REG2_FALC_LED1 << (2 *ch))); - } - - CPC_TTY_UNLOCK(card, flags); - - return -EINVAL; - } - - if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { - /* failed to send */ - CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name); - return 0; - } - return count; -} - -/* - * PC300 TTY Write Room routine - * - * This routine returns the numbers of characteres the tty driver will accept - * for queuing to be written. - * o return MTU - */ -static int cpc_tty_write_room(struct tty_struct *tty) -{ - st_cpc_tty_area *cpc_tty; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY to write room\n"); - return -ENODEV; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); - return -ENODEV; - } - - CPC_TTY_DBG("%s: write room\n",cpc_tty->name); - - return CPC_TTY_MAX_MTU; -} - -/* - * PC300 TTY chars in buffer routine - * - * This routine returns the chars number in the transmission buffer - * o returns 0 - */ -static int cpc_tty_chars_in_buffer(struct tty_struct *tty) -{ - st_cpc_tty_area *cpc_tty; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n"); - return -ENODEV; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); - return -ENODEV; - } - - return(0); -} - -static int pc300_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - st_cpc_tty_area *cpc_tty; - - CPC_TTY_DBG("%s: set:%x clear:%x\n", __FUNCTION__, set, clear); - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n"); - return -ENODEV; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if (set & TIOCM_RTS) - cpc_tty_signal_on(cpc_tty->pc300dev, CTL_RTS); - if (set & TIOCM_DTR) - cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR); - - if (clear & TIOCM_RTS) - cpc_tty_signal_off(cpc_tty->pc300dev, CTL_RTS); - if (clear & TIOCM_DTR) - cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR); - - return 0; -} - -static int pc300_tiocmget(struct tty_struct *tty, struct file *file) -{ - unsigned int result; - unsigned char status; - unsigned long flags; - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) tty->driver_data; - pc300dev_t *pc300dev = cpc_tty->pc300dev; - pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; - pc300_t *card = (pc300_t *) pc300chan->card; - int ch = pc300chan->channel; - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - CPC_TTY_DBG("%s-tty: tiocmget\n", - ((struct net_device*)(pc300dev->hdlc))->name); - - CPC_TTY_LOCK(card, flags); - status = cpc_readb(card->hw.scabase+M_REG(CTL,ch)); - CPC_TTY_UNLOCK(card,flags); - - result = ((status & CTL_DTR) ? TIOCM_DTR : 0) | - ((status & CTL_RTS) ? TIOCM_RTS : 0); - - return result; -} - -/* - * PC300 TTY Flush Buffer routine - * - * This routine resets the transmission buffer - */ -static void cpc_tty_flush_buffer(struct tty_struct *tty) -{ - st_cpc_tty_area *cpc_tty; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY to flush buffer\n"); - return; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); - return; - } - - CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name); - - tty_wakeup(tty); - return; -} - -/* - * PC300 TTY Hangup routine - * - * This routine is called by the tty driver to hangup the interface - * o clear DTR signal - */ - -static void cpc_tty_hangup(struct tty_struct *tty) -{ - st_cpc_tty_area *cpc_tty; - int res; - - if (!tty || !tty->driver_data ) { - CPC_TTY_DBG("hdlcX-tty: no TTY to hangup\n"); - return ; - } - - cpc_tty = (st_cpc_tty_area *) tty->driver_data; - - if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { - CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); - return ; - } - if (!serial_drv.refcount && cpc_tty_unreg_flag) { - cpc_tty_unreg_flag = 0; - CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name); - if ((res=tty_unregister_driver(&serial_drv))) { - CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n", - cpc_tty->name,res); - } - } - cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR); -} - -/* - * PC300 TTY RX work routine - * This routine treats RX work - * o verify read buffer - * o call the line disc. read - * o free memory - */ -static void cpc_tty_rx_work(struct work_struct *work) -{ - st_cpc_tty_area *cpc_tty; - unsigned long port; - int i, j; - 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; - - 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]; - - if ((buf=cpc_tty->buf_rx.first) != NULL) { - if (cpc_tty->tty) { - ld = tty_ldisc_ref(cpc_tty->tty); - if (ld) { - if (ld->receive_buf) { - CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name); - ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size); - } - tty_ldisc_deref(ld); - } - } - cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; - kfree((void *)buf); - buf = cpc_tty->buf_rx.first; - flg_rx = 1; - } - if (++port == CPC_TTY_NPORTS) port = 0; - } - } -} - -/* - * PC300 TTY RX work routine - * - * This routine treats RX interrupt. - * o read all frames in card - * o verify the frame size - * o read the frame in rx buffer - */ -static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan) -{ - volatile pcsca_bd_t __iomem * ptdescr; - volatile unsigned char status; - pc300_t *card = (pc300_t *)pc300chan->card; - int ch = pc300chan->channel; - - /* dma buf read */ - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + - RX_BD_ADDR(ch, pc300chan->rx_first_bd)); - while (pc300chan->rx_first_bd != pc300chan->rx_last_bd) { - status = cpc_readb(&ptdescr->status); - cpc_writeb(&ptdescr->status, 0); - cpc_writeb(&ptdescr->len, 0); - pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & - (N_DMA_RX_BUF - 1); - if (status & DST_EOM) { - break; /* end of message */ - } - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->next)); - } -} - -void cpc_tty_receive(pc300dev_t *pc300dev) -{ - st_cpc_tty_area *cpc_tty; - pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; - pc300_t *card = (pc300_t *)pc300chan->card; - int ch = pc300chan->channel; - volatile pcsca_bd_t __iomem * ptdescr; - struct net_device_stats *stats = hdlc_stats(pc300dev->dev); - int rx_len, rx_aux; - volatile unsigned char status; - unsigned short first_bd = pc300chan->rx_first_bd; - st_cpc_rx_buf *new = NULL; - unsigned char dsr_rx; - - if (pc300dev->cpc_tty == NULL) { - return; - } - - dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch)); - - cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty; - - while (1) { - rx_len = 0; - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); - while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { - rx_len += cpc_readw(&ptdescr->len); - first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); - if (status & DST_EOM) { - break; - } - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next)); - } - - if (!rx_len) { - if (dsr_rx & DSR_BOF) { - /* update EDA */ - cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), - RX_BD_ADDR(ch, pc300chan->rx_last_bd)); - } - kfree(new); - return; - } - - if (rx_len > CPC_TTY_MAX_MTU) { - /* Free RX descriptors */ - CPC_TTY_DBG("%s: frame size is invalid.\n",cpc_tty->name); - stats->rx_errors++; - stats->rx_frame_errors++; - cpc_tty_rx_disc_frame(pc300chan); - continue; - } - - new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC); - if (!new) { - cpc_tty_rx_disc_frame(pc300chan); - continue; - } - - /* dma buf read */ - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + - RX_BD_ADDR(ch, pc300chan->rx_first_bd)); - - rx_len = 0; /* counter frame size */ - - while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { - rx_aux = cpc_readw(&ptdescr->len); - if ((status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) - || (rx_aux > BD_DEF_LEN)) { - CPC_TTY_DBG("%s: reception error\n", cpc_tty->name); - stats->rx_errors++; - if (status & DST_OVR) { - stats->rx_fifo_errors++; - } - if (status & DST_CRC) { - stats->rx_crc_errors++; - } - if ((status & (DST_RBIT | DST_SHRT | DST_ABT)) || - (rx_aux > BD_DEF_LEN)) { - stats->rx_frame_errors++; - } - /* discard remainig descriptors used by the bad frame */ - CPC_TTY_DBG("%s: reception error - discard descriptors", - cpc_tty->name); - cpc_tty_rx_disc_frame(pc300chan); - rx_len = 0; - kfree(new); - new = NULL; - break; /* read next frame - while(1) */ - } - - if (cpc_tty->state != CPC_TTY_ST_OPEN) { - /* Free RX descriptors */ - cpc_tty_rx_disc_frame(pc300chan); - stats->rx_dropped++; - rx_len = 0; - kfree(new); - new = NULL; - break; /* read next frame - while(1) */ - } - - /* read the segment of the frame */ - if (rx_aux != 0) { - memcpy_fromio((new->data + rx_len), - (void __iomem *)(card->hw.rambase + - cpc_readl(&ptdescr->ptbuf)), rx_aux); - rx_len += rx_aux; - } - cpc_writeb(&ptdescr->status,0); - cpc_writeb(&ptdescr->len, 0); - pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & - (N_DMA_RX_BUF -1); - if (status & DST_EOM)break; - - ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + - cpc_readl(&ptdescr->next)); - } - /* update pointer */ - pc300chan->rx_last_bd = (pc300chan->rx_first_bd - 1) & - (N_DMA_RX_BUF - 1) ; - if (!(dsr_rx & DSR_BOF)) { - /* update EDA */ - cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), - RX_BD_ADDR(ch, pc300chan->rx_last_bd)); - } - if (rx_len != 0) { - stats->rx_bytes += rx_len; - - if (pc300dev->trace_on) { - cpc_tty_trace(pc300dev, new->data,rx_len, 'R'); - } - new->size = rx_len; - new->next = NULL; - if (cpc_tty->buf_rx.first == NULL) { - cpc_tty->buf_rx.first = new; - cpc_tty->buf_rx.last = new; - } else { - cpc_tty->buf_rx.last->next = new; - cpc_tty->buf_rx.last = new; - } - schedule_work(&(cpc_tty->tty_rx_work)); - stats->rx_packets++; - } - } -} - -/* - * PC300 TTY TX work routine - * - * This routine treats TX interrupt. - * o if need call line discipline wakeup - * o call wake_up_interruptible - */ -static void cpc_tty_tx_work(struct work_struct *work) -{ - 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); - - if ((tty = cpc_tty->tty) == NULL) { - CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name); - return; - } - tty_wakeup(tty); -} - -/* - * PC300 TTY send to card routine - * - * This routine send data to card. - * o clear descriptors - * o write data to DMA buffers - * o start the transmission - */ -static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) -{ - pc300ch_t *chan = (pc300ch_t *)dev->chan; - pc300_t *card = (pc300_t *)chan->card; - int ch = chan->channel; - struct net_device_stats *stats = hdlc_stats(dev->dev); - unsigned long flags; - volatile pcsca_bd_t __iomem *ptdescr; - int i, nchar; - int tosend = len; - int nbuf = ((len - 1)/BD_DEF_LEN) + 1; - unsigned char *pdata=buf; - - CPC_TTY_DBG("%s:cpc_tty_send_to_cars len=%i", - (st_cpc_tty_area *)dev->cpc_tty->name,len); - - if (nbuf >= card->chan[ch].nfree_tx_bd) { - return 1; - } - - /* write buffer to DMA buffers */ - CPC_TTY_DBG("%s: call dma_buf_write\n", - (st_cpc_tty_area *)dev->cpc_tty->name); - for (i = 0 ; i < nbuf ; i++) { - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + - TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); - nchar = (BD_DEF_LEN > tosend) ? tosend : BD_DEF_LEN; - if (cpc_readb(&ptdescr->status) & DST_OSB) { - memcpy_toio((void __iomem *)(card->hw.rambase + - cpc_readl(&ptdescr->ptbuf)), - &pdata[len - tosend], - nchar); - card->chan[ch].nfree_tx_bd--; - if ((i + 1) == nbuf) { - /* This must be the last BD to be used */ - cpc_writeb(&ptdescr->status, DST_EOM); - } else { - cpc_writeb(&ptdescr->status, 0); - } - cpc_writew(&ptdescr->len, nchar); - } else { - CPC_TTY_DBG("%s: error in dma_buf_write\n", - (st_cpc_tty_area *)dev->cpc_tty->name); - stats->tx_dropped++; - return 1; - } - tosend -= nchar; - card->chan[ch].tx_next_bd = - (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1); - } - - if (dev->trace_on) { - cpc_tty_trace(dev, buf, len,'T'); - } - - /* start transmission */ - CPC_TTY_DBG("%s: start transmission\n", - (st_cpc_tty_area *)dev->cpc_tty->name); - - CPC_TTY_LOCK(card, flags); - cpc_writeb(card->hw.scabase + DTX_REG(EDAL, ch), - TX_BD_ADDR(ch, chan->tx_next_bd)); - cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA); - cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE); - - if (card->hw.type == PC300_TE) { - cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, - cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) | - (CPLD_REG2_FALC_LED1 << (2 * ch))); - } - CPC_TTY_UNLOCK(card, flags); - return 0; -} - -/* - * PC300 TTY trace routine - * - * This routine send trace of connection to application. - * o clear descriptors - * o write data to DMA buffers - * o start the transmission - */ - -static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx) -{ - struct sk_buff *skb; - - if ((skb = dev_alloc_skb(10 + len)) == NULL) { - /* out of memory */ - CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name); - return; - } - - skb_put (skb, 10 + len); - skb->dev = dev->dev; - skb->protocol = htons(ETH_P_CUST); - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_HOST; - skb->len = 10 + len; - - skb_copy_to_linear_data(skb, dev->dev->name, 5); - skb->data[5] = '['; - skb->data[6] = rxtx; - skb->data[7] = ']'; - skb->data[8] = ':'; - skb->data[9] = ' '; - skb_copy_to_linear_data_offset(skb, 10, buf, len); - netif_rx(skb); -} - -/* - * PC300 TTY unregister service routine - * - * This routine unregister one interface. - */ -void cpc_tty_unregister_service(pc300dev_t *pc300dev) -{ - st_cpc_tty_area *cpc_tty; - ulong flags; - int res; - - if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == NULL) { - CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name); - return; - } - CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name); - - if (cpc_tty->pc300dev != pc300dev) { - CPC_TTY_DBG("%s: invalid tty ptr=%s\n", - pc300dev->dev->name, cpc_tty->name); - return; - } - - if (--cpc_tty_cnt == 0) { - if (serial_drv.refcount) { - CPC_TTY_DBG("%s: unregister is not possible, refcount=%d", - cpc_tty->name, serial_drv.refcount); - cpc_tty_cnt++; - cpc_tty_unreg_flag = 1; - return; - } else { - CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name); - if ((res=tty_unregister_driver(&serial_drv))) { - CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n", - cpc_tty->name,res); - } - } - } - CPC_TTY_LOCK(pc300dev->chan->card,flags); - cpc_tty->tty = NULL; - CPC_TTY_UNLOCK(pc300dev->chan->card, flags); - cpc_tty->tty_minor = 0; - cpc_tty->state = CPC_TTY_ST_IDLE; -} - -/* - * PC300 TTY trigger poll routine - * This routine is called by pc300driver to treats Tx interrupt. - */ -void cpc_tty_trigger_poll(pc300dev_t *pc300dev) -{ - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty; - if (!cpc_tty) { - return; - } - schedule_work(&(cpc_tty->tty_tx_work)); -} - -/* - * PC300 TTY reset var routine - * This routine is called by pc300driver to init the TTY area. - */ - -void cpc_tty_reset_var(void) -{ - int i ; - - CPC_TTY_DBG("hdlcX-tty: reset variables\n"); - /* reset the tty_driver structure - serial_drv */ - memset(&serial_drv, 0, sizeof(struct tty_driver)); - for (i=0; i < CPC_TTY_NPORTS; i++){ - memset(&cpc_tty_area[i],0, sizeof(st_cpc_tty_area)); - } -} diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index bf1b0159042..5b72f7f8c51 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -1,7 +1,7 @@ /* * Cyclades PC300 synchronous serial card driver for Linux * - * Copyright (C) 2000-2007 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 2000-2008 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -11,12 +11,14 @@ * * Sources of information: * Hitachi HD64572 SCA-II User's Manual - * Cyclades PC300 Linux driver + * Original Cyclades PC300 Linux driver * * This driver currently supports only PC300/RSV (V.24/V.35) and * PC300/X21 cards. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -37,17 +39,11 @@ #include "hd64572.h" -static const char* version = "Cyclades PC300 driver version: 1.17"; -static const char* devname = "PC300"; - #undef DEBUG_PKT #define DEBUG_RINGS #define PC300_PLX_SIZE 0x80 /* PLX control window size (128 B) */ #define PC300_SCA_SIZE 0x400 /* SCA window size (1 KB) */ -#define ALL_PAGES_ALWAYS_MAPPED -#define NEED_DETECT_RAM -#define NEED_SCA_MSCI_INTR #define MAX_TX_BUFFERS 10 static int pci_clock_freq = 33000000; @@ -81,7 +77,8 @@ typedef struct { typedef struct port_s { - struct net_device *dev; + struct napi_struct napi; + struct net_device *netdev; struct card_s *card; spinlock_t lock; /* TX lock */ sync_serial_settings settings; @@ -93,7 +90,7 @@ typedef struct port_s { u16 txin; /* tx ring buffer 'in' and 'last' pointers */ u16 txlast; u8 rxs, txs, tmc; /* SCA registers */ - u8 phy_node; /* physical port # - 0 or 1 */ + u8 chan; /* physical port # - 0 or 1 */ }port_t; @@ -114,21 +111,10 @@ typedef struct card_s { }card_t; -#define sca_in(reg, card) readb(card->scabase + (reg)) -#define sca_out(value, reg, card) writeb(value, card->scabase + (reg)) -#define sca_inw(reg, card) readw(card->scabase + (reg)) -#define sca_outw(value, reg, card) writew(value, card->scabase + (reg)) -#define sca_inl(reg, card) readl(card->scabase + (reg)) -#define sca_outl(value, reg, card) writel(value, card->scabase + (reg)) - -#define port_to_card(port) (port->card) -#define log_node(port) (port->phy_node) -#define phy_node(port) (port->phy_node) -#define winbase(card) (card->rambase) #define get_port(card, port) ((port) < (card)->n_ports ? \ (&(card)->ports[port]) : (NULL)) -#include "hd6457x.c" +#include "hd64572.c" static void pc300_set_iface(port_t *port) @@ -139,8 +125,8 @@ static void pc300_set_iface(port_t *port) u8 rxs = port->rxs & CLK_BRG_MASK; u8 txs = port->txs & CLK_BRG_MASK; - sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS, - port_to_card(port)); + sca_out(EXS_TES1, (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS, + port->card); switch(port->settings.clock_type) { case CLOCK_INT: rxs |= CLK_BRG; /* BRG output */ @@ -172,10 +158,10 @@ static void pc300_set_iface(port_t *port) if (port->card->type == PC300_RSV) { if (port->iface == IF_IFACE_V35) writel(card->init_ctrl_value | - PC300_CHMEDIA_MASK(port->phy_node), init_ctrl); + PC300_CHMEDIA_MASK(port->chan), init_ctrl); else writel(card->init_ctrl_value & - ~PC300_CHMEDIA_MASK(port->phy_node), init_ctrl); + ~PC300_CHMEDIA_MASK(port->chan), init_ctrl); } } @@ -280,10 +266,8 @@ static void pc300_pci_remove_one(struct pci_dev *pdev) card_t *card = pci_get_drvdata(pdev); for (i = 0; i < 2; i++) - if (card->ports[i].card) { - struct net_device *dev = port_to_dev(&card->ports[i]); - unregister_hdlc_device(dev); - } + if (card->ports[i].card) + unregister_hdlc_device(card->ports[i].netdev); if (card->irq) free_irq(card->irq, card); @@ -297,18 +281,23 @@ static void pc300_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - if (card->ports[0].dev) - free_netdev(card->ports[0].dev); - if (card->ports[1].dev) - free_netdev(card->ports[1].dev); + if (card->ports[0].netdev) + free_netdev(card->ports[0].netdev); + if (card->ports[1].netdev) + free_netdev(card->ports[1].netdev); kfree(card); } +static const struct net_device_ops pc300_ops = { + .ndo_open = pc300_open, + .ndo_stop = pc300_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = pc300_ioctl, +}; - -static int __devinit pc300_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int pc300_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { card_t *card; u32 __iomem *p; @@ -318,12 +307,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, u32 scaphys; /* SCA memory base */ u32 plxphys; /* PLX registers memory base */ -#ifndef MODULE - static int printed_version; - if (!printed_version++) - printk(KERN_INFO "%s\n", version); -#endif - i = pci_enable_device(pdev); if (i) return i; @@ -336,55 +319,33 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { - printk(KERN_ERR "pc300: unable to allocate memory\n"); pci_release_regions(pdev); pci_disable_device(pdev); return -ENOBUFS; } pci_set_drvdata(pdev, card); - if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 || - pdev->device == PCI_DEVICE_ID_PC300_TE_2) - card->type = PC300_TE; /* not fully supported */ - else if (card->init_ctrl_value & PC300_CTYPE_MASK) - card->type = PC300_X21; - else - card->type = PC300_RSV; - - if (pdev->device == PCI_DEVICE_ID_PC300_RX_1 || - pdev->device == PCI_DEVICE_ID_PC300_TE_1) - card->n_ports = 1; - else - card->n_ports = 2; - - for (i = 0; i < card->n_ports; i++) - if (!(card->ports[i].dev = alloc_hdlcdev(&card->ports[i]))) { - printk(KERN_ERR "pc300: unable to allocate memory\n"); - pc300_pci_remove_one(pdev); - return -ENOMEM; - } - if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE || pci_resource_len(pdev, 2) != PC300_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { - printk(KERN_ERR "pc300: invalid card EEPROM parameters\n"); + pr_err("invalid card EEPROM parameters\n"); pc300_pci_remove_one(pdev); return -EFAULT; } - plxphys = pci_resource_start(pdev,0) & PCI_BASE_ADDRESS_MEM_MASK; + plxphys = pci_resource_start(pdev, 0) & PCI_BASE_ADDRESS_MEM_MASK; card->plxbase = ioremap(plxphys, PC300_PLX_SIZE); - scaphys = pci_resource_start(pdev,2) & PCI_BASE_ADDRESS_MEM_MASK; + scaphys = pci_resource_start(pdev, 2) & PCI_BASE_ADDRESS_MEM_MASK; card->scabase = ioremap(scaphys, PC300_SCA_SIZE); - ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK; - card->rambase = ioremap(ramphys, pci_resource_len(pdev,3)); + ramphys = pci_resource_start(pdev, 3) & PCI_BASE_ADDRESS_MEM_MASK; + card->rambase = pci_ioremap_bar(pdev, 3); if (card->plxbase == NULL || card->scabase == NULL || card->rambase == NULL) { - printk(KERN_ERR "pc300: ioremap() failed\n"); + pr_err("ioremap() failed\n"); pc300_pci_remove_one(pdev); } @@ -393,6 +354,27 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, card->init_ctrl_value = readl(&((plx9050 __iomem *)card->scabase)->init_ctrl); pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys); + if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 || + pdev->device == PCI_DEVICE_ID_PC300_TE_2) + card->type = PC300_TE; /* not fully supported */ + else if (card->init_ctrl_value & PC300_CTYPE_MASK) + card->type = PC300_X21; + else + card->type = PC300_RSV; + + if (pdev->device == PCI_DEVICE_ID_PC300_RX_1 || + pdev->device == PCI_DEVICE_ID_PC300_TE_1) + card->n_ports = 1; + else + card->n_ports = 2; + + for (i = 0; i < card->n_ports; i++) + if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) { + pr_err("unable to allocate memory\n"); + pc300_pci_remove_one(pdev); + return -ENOMEM; + } + /* Reset PLX */ p = &card->plxbase->init_ctrl; writel(card->init_ctrl_value | 0x40000000, p); @@ -429,15 +411,14 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, card->buff_offset = card->n_ports * sizeof(pkt_desc) * (card->tx_ring_buffers + card->rx_ring_buffers); - printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, " - "using %u TX + %u RX packets rings\n", - card->type == PC300_X21 ? "X21" : - card->type == PC300_TE ? "TE" : "RSV", - ramsize / 1024, ramphys, pdev->irq, - card->tx_ring_buffers, card->rx_ring_buffers); + pr_info("PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n", + card->type == PC300_X21 ? "X21" : + card->type == PC300_TE ? "TE" : "RSV", + ramsize / 1024, ramphys, pdev->irq, + card->tx_ring_buffers, card->rx_ring_buffers); if (card->tx_ring_buffers < 1) { - printk(KERN_ERR "pc300: RAM test failed\n"); + pr_err("RAM test failed\n"); pc300_pci_remove_one(pdev); return -EFAULT; } @@ -446,9 +427,8 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, writew(0x0041, &card->plxbase->intr_ctrl_stat); /* Allocate IRQ */ - if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) { - printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n", - pdev->irq); + if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) { + pr_warn("could not allocate IRQ%d\n", pdev->irq); pc300_pci_remove_one(pdev); return -EBUSY; } @@ -463,18 +443,16 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, for (i = 0; i < card->n_ports; i++) { port_t *port = &card->ports[i]; - struct net_device *dev = port_to_dev(port); + struct net_device *dev = port->netdev; hdlc_device *hdlc = dev_to_hdlc(dev); - port->phy_node = i; + port->chan = i; spin_lock_init(&port->lock); dev->irq = card->irq; dev->mem_start = ramphys; dev->mem_end = ramphys + ramsize - 1; dev->tx_queue_len = 50; - dev->do_ioctl = pc300_ioctl; - dev->open = pc300_open; - dev->stop = pc300_close; + dev->netdev_ops = &pc300_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; @@ -484,24 +462,22 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, else port->iface = IF_IFACE_V35; + sca_init_port(port); if (register_hdlc_device(dev)) { - printk(KERN_ERR "pc300: unable to register hdlc " - "device\n"); + pr_err("unable to register hdlc device\n"); port->card = NULL; pc300_pci_remove_one(pdev); return -ENOBUFS; } - sca_init_sync_port(port); /* Set up SCA memory */ - printk(KERN_INFO "%s: PC300 node %d\n", - dev->name, port->phy_node); + netdev_info(dev, "PC300 channel %d\n", port->chan); } return 0; } -static struct pci_device_id pc300_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(pc300_pci_tbl) = { { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID, @@ -524,15 +500,12 @@ static struct pci_driver pc300_pci_driver = { static int __init pc300_init_module(void) { -#ifdef MODULE - printk(KERN_INFO "%s\n", version); -#endif if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) { - printk(KERN_ERR "pc300: Invalid PCI clock frequency\n"); + pr_err("Invalid PCI clock frequency\n"); return -EINVAL; } if (use_crystal_clock != 0 && use_crystal_clock != 1) { - printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n"); + pr_err("Invalid 'use_crystal_clock' value\n"); return -EINVAL; } diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index b595b64e753..fe4e3ece3c4 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -1,7 +1,7 @@ /* * Goramo PCI200SYN synchronous serial card driver for Linux * - * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 2002-2008 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -14,8 +14,11 @@ * PLX Technology Inc. PCI9052 Data Book */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> +#include <linux/capability.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/fcntl.h> @@ -33,17 +36,11 @@ #include "hd64572.h" -static const char* version = "Goramo PCI200SYN driver version: 1.16"; -static const char* devname = "PCI200SYN"; - #undef DEBUG_PKT #define DEBUG_RINGS #define PCI200SYN_PLX_SIZE 0x80 /* PLX control window size (128b) */ #define PCI200SYN_SCA_SIZE 0x400 /* SCA window size (1Kb) */ -#define ALL_PAGES_ALWAYS_MAPPED -#define NEED_DETECT_RAM -#define NEED_SCA_MSCI_INTR #define MAX_TX_BUFFERS 10 static int pci_clock_freq = 33000000; @@ -68,7 +65,8 @@ typedef struct { typedef struct port_s { - struct net_device *dev; + struct napi_struct napi; + struct net_device *netdev; struct card_s *card; spinlock_t lock; /* TX lock */ sync_serial_settings settings; @@ -79,7 +77,7 @@ typedef struct port_s { u16 txin; /* tx ring buffer 'in' and 'last' pointers */ u16 txlast; u8 rxs, txs, tmc; /* SCA registers */ - u8 phy_node; /* physical port # - 0 or 1 */ + u8 chan; /* physical port # - 0 or 1 */ }port_t; @@ -97,17 +95,6 @@ typedef struct card_s { }card_t; -#define sca_in(reg, card) readb(card->scabase + (reg)) -#define sca_out(value, reg, card) writeb(value, card->scabase + (reg)) -#define sca_inw(reg, card) readw(card->scabase + (reg)) -#define sca_outw(value, reg, card) writew(value, card->scabase + (reg)) -#define sca_inl(reg, card) readl(card->scabase + (reg)) -#define sca_outl(value, reg, card) writel(value, card->scabase + (reg)) - -#define port_to_card(port) (port->card) -#define log_node(port) (port->phy_node) -#define phy_node(port) (port->phy_node) -#define winbase(card) (card->rambase) #define get_port(card, port) (&card->ports[port]) #define sca_flush(card) (sca_in(IER0, card)); @@ -127,7 +114,7 @@ static inline void new_memcpy_toio(char __iomem *dest, char *src, int length) #undef memcpy_toio #define memcpy_toio new_memcpy_toio -#include "hd6457x.c" +#include "hd64572.c" static void pci200_set_iface(port_t *port) @@ -137,8 +124,8 @@ static void pci200_set_iface(port_t *port) u8 rxs = port->rxs & CLK_BRG_MASK; u8 txs = port->txs & CLK_BRG_MASK; - sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS, - port_to_card(port)); + sca_out(EXS_TES1, (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS, + port->card); switch(port->settings.clock_type) { case CLOCK_INT: rxs |= CLK_BRG; /* BRG output */ @@ -180,7 +167,7 @@ static int pci200_open(struct net_device *dev) sca_open(dev); pci200_set_iface(port); - sca_flush(port_to_card(port)); + sca_flush(port->card); return 0; } @@ -189,7 +176,7 @@ static int pci200_open(struct net_device *dev) static int pci200_close(struct net_device *dev) { sca_close(dev); - sca_flush(port_to_card(dev_to_port(dev))); + sca_flush(dev_to_port(dev)->card); hdlc_close(dev); return 0; } @@ -235,14 +222,14 @@ static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ + return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; memcpy(&port->settings, &new_line, size); /* Update settings */ pci200_set_iface(port); - sca_flush(port_to_card(port)); + sca_flush(port->card); return 0; default: @@ -258,10 +245,8 @@ static void pci200_pci_remove_one(struct pci_dev *pdev) card_t *card = pci_get_drvdata(pdev); for (i = 0; i < 2; i++) - if (card->ports[i].card) { - struct net_device *dev = port_to_dev(&card->ports[i]); - unregister_hdlc_device(dev); - } + if (card->ports[i].card) + unregister_hdlc_device(card->ports[i].netdev); if (card->irq) free_irq(card->irq, card); @@ -275,18 +260,23 @@ static void pci200_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - if (card->ports[0].dev) - free_netdev(card->ports[0].dev); - if (card->ports[1].dev) - free_netdev(card->ports[1].dev); + if (card->ports[0].netdev) + free_netdev(card->ports[0].netdev); + if (card->ports[1].netdev) + free_netdev(card->ports[1].netdev); kfree(card); } +static const struct net_device_ops pci200_ops = { + .ndo_open = pci200_open, + .ndo_stop = pci200_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = pci200_ioctl, +}; - -static int __devinit pci200_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int pci200_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { card_t *card; u32 __iomem *p; @@ -296,12 +286,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, u32 scaphys; /* SCA memory base */ u32 plxphys; /* PLX registers memory base */ -#ifndef MODULE - static int printed_version; - if (!printed_version++) - printk(KERN_INFO "%s\n", version); -#endif - i = pci_enable_device(pdev); if (i) return i; @@ -314,16 +298,15 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { - printk(KERN_ERR "pci200syn: unable to allocate memory\n"); pci_release_regions(pdev); pci_disable_device(pdev); return -ENOBUFS; } pci_set_drvdata(pdev, card); - card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); - card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); - if (!card->ports[0].dev || !card->ports[1].dev) { - printk(KERN_ERR "pci200syn: unable to allocate memory\n"); + card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]); + card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]); + if (!card->ports[0].netdev || !card->ports[1].netdev) { + pr_err("unable to allocate memory\n"); pci200_pci_remove_one(pdev); return -ENOMEM; } @@ -331,7 +314,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE || pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { - printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n"); + pr_err("invalid card EEPROM parameters\n"); pci200_pci_remove_one(pdev); return -EFAULT; } @@ -343,12 +326,12 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, card->scabase = ioremap(scaphys, PCI200SYN_SCA_SIZE); ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK; - card->rambase = ioremap(ramphys, pci_resource_len(pdev,3)); + card->rambase = pci_ioremap_bar(pdev, 3); if (card->plxbase == NULL || card->scabase == NULL || card->rambase == NULL) { - printk(KERN_ERR "pci200syn: ioremap() failed\n"); + pr_err("ioremap() failed\n"); pci200_pci_remove_one(pdev); return -EFAULT; } @@ -374,21 +357,12 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers + card->rx_ring_buffers); - printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +" - " %u RX packets rings\n", ramsize / 1024, ramphys, - pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers); - - if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) { - printk(KERN_ERR "Detected PCI200SYN card with old " - "configuration data.\n"); - printk(KERN_ERR "See <http://www.kernel.org/pub/" - "linux/utils/net/hdlc/pci200syn/> for update.\n"); - printk(KERN_ERR "The card will stop working with" - " future versions of Linux if not updated.\n"); - } + pr_info("%u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n", + ramsize / 1024, ramphys, + pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers); if (card->tx_ring_buffers < 1) { - printk(KERN_ERR "pci200syn: RAM test failed\n"); + pr_err("RAM test failed\n"); pci200_pci_remove_one(pdev); return -EFAULT; } @@ -398,9 +372,8 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, writew(readw(p) | 0x0040, p); /* Allocate IRQ */ - if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) { - printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n", - pdev->irq); + if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) { + pr_warn("could not allocate IRQ%d\n", pdev->irq); pci200_pci_remove_one(pdev); return -EBUSY; } @@ -410,33 +383,29 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, for (i = 0; i < 2; i++) { port_t *port = &card->ports[i]; - struct net_device *dev = port_to_dev(port); + struct net_device *dev = port->netdev; hdlc_device *hdlc = dev_to_hdlc(dev); - port->phy_node = i; + port->chan = i; spin_lock_init(&port->lock); dev->irq = card->irq; dev->mem_start = ramphys; dev->mem_end = ramphys + ramsize - 1; dev->tx_queue_len = 50; - dev->do_ioctl = pci200_ioctl; - dev->open = pci200_open; - dev->stop = pci200_close; + dev->netdev_ops = &pci200_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; port->card = card; + sca_init_port(port); if (register_hdlc_device(dev)) { - printk(KERN_ERR "pci200syn: unable to register hdlc " - "device\n"); + pr_err("unable to register hdlc device\n"); port->card = NULL; pci200_pci_remove_one(pdev); return -ENOBUFS; } - sca_init_sync_port(port); /* Set up SCA memory */ - printk(KERN_INFO "%s: PCI200SYN node %d\n", - dev->name, port->phy_node); + netdev_info(dev, "PCI200SYN channel %d\n", port->chan); } sca_flush(card); @@ -445,9 +414,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, -static struct pci_device_id pci200_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, - PCI_DEVICE_ID_PLX_9050, 0, 0, 0 }, +static DEFINE_PCI_DEVICE_TABLE(pci200_pci_tbl) = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 }, { 0, } @@ -464,11 +431,8 @@ static struct pci_driver pci200_pci_driver = { static int __init pci200_init_module(void) { -#ifdef MODULE - printk(KERN_INFO "%s\n", version); -#endif if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) { - printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n"); + pr_err("Invalid PCI clock frequency\n"); return -EINVAL; } return pci_register_driver(&pci200_pci_driver); diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index e59255a155a..1b89ecf0959 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -37,13 +37,14 @@ * Known problem: this driver wasn't tested on multiprocessor machine. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/ptrace.h> #include <linux/fcntl.h> #include <linux/ioport.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/netdevice.h> @@ -56,6 +57,7 @@ #include <net/net_namespace.h> #include <net/arp.h> +#include <net/Space.h> #include <asm/io.h> #include <asm/types.h> @@ -68,7 +70,6 @@ /* device private data */ struct net_local { - struct net_device_stats stats; struct timer_list watchdog; spinlock_t lock; @@ -115,9 +116,9 @@ static int sbni_pci_probe( struct net_device * ); static struct net_device *sbni_probe1(struct net_device *, unsigned long, int); static int sbni_open( struct net_device * ); static int sbni_close( struct net_device * ); -static int sbni_start_xmit( struct sk_buff *, struct net_device * ); +static netdev_tx_t sbni_start_xmit(struct sk_buff *, + struct net_device * ); 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 * ); @@ -148,14 +149,10 @@ static int enslave( struct net_device *, struct net_device * ); static int emancipate( struct net_device * ); #endif -#ifdef __i386__ -#define ASM_CRC 1 -#endif - static const char version[] = "Granch SBNI12 driver ver 5.0.1 Jun 22 2001 Denis I.Timofeev.\n"; -static int skip_pci_probe __initdata = 0; +static bool skip_pci_probe __initdata = false; static int scandone __initdata = 0; static int num __initdata = 0; @@ -176,7 +173,7 @@ static u32 mac[ SBNI_MAX_NUM_CARDS ] __initdata; #ifndef MODULE typedef u32 iarr[]; -static iarr __initdata *dest[5] = { &io, &irq, &baud, &rxl, &mac }; +static iarr *dest[5] __initdata = { &io, &irq, &baud, &rxl, &mac }; #endif /* A zero-terminated list of I/O addresses to be probed on ISA bus */ @@ -186,6 +183,7 @@ static unsigned int netcard_portlist[ ] __initdata = { 0x2b0, 0x2b4, 0x2c0, 0x2c4, 0x2d0, 0x2d4, 0x2e0, 0x2e4, 0x2f0, 0x2f4, 0 }; +#define NET_LOCAL_LOCK(dev) (((struct net_local *)netdev_priv(dev))->lock) /* * Look for SBNI card which addr stored in dev->base_addr, if nonzero. @@ -195,39 +193,46 @@ static unsigned int netcard_portlist[ ] __initdata = { static inline int __init sbni_isa_probe( struct net_device *dev ) { - if( dev->base_addr > 0x1ff - && request_region( dev->base_addr, SBNI_IO_EXTENT, dev->name ) - && sbni_probe1( dev, dev->base_addr, dev->irq ) ) + if( dev->base_addr > 0x1ff && + request_region( dev->base_addr, SBNI_IO_EXTENT, dev->name ) && + sbni_probe1( dev, dev->base_addr, dev->irq ) ) return 0; else { - printk( KERN_ERR "sbni: base address 0x%lx is busy, or adapter " - "is malfunctional!\n", dev->base_addr ); + pr_err("base address 0x%lx is busy, or adapter is malfunctional!\n", + dev->base_addr); return -ENODEV; } } +static const struct net_device_ops sbni_netdev_ops = { + .ndo_open = sbni_open, + .ndo_stop = sbni_close, + .ndo_start_xmit = sbni_start_xmit, + .ndo_set_rx_mode = set_multicast_list, + .ndo_do_ioctl = sbni_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static void __init sbni_devsetup(struct net_device *dev) { ether_setup( dev ); - dev->open = &sbni_open; - dev->stop = &sbni_close; - dev->hard_start_xmit = &sbni_start_xmit; - dev->get_stats = &sbni_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &sbni_ioctl; + dev->netdev_ops = &sbni_netdev_ops; } int __init sbni_probe(int unit) { struct net_device *dev; - static unsigned version_printed __initdata = 0; int err; dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup); if (!dev) return -ENOMEM; + dev->netdev_ops = &sbni_netdev_ops; + sprintf(dev->name, "sbni%d", unit); netdev_boot_setup_check(dev); @@ -243,8 +248,7 @@ int __init sbni_probe(int unit) free_netdev(dev); return err; } - if( version_printed++ == 0 ) - printk( KERN_INFO "%s", version ); + pr_info_once("%s", version); return 0; } @@ -278,8 +282,8 @@ static int __init sbni_init(struct net_device *dev) for( i = 0; netcard_portlist[ i ]; ++i ) { int ioaddr = netcard_portlist[ i ]; - if( request_region( ioaddr, SBNI_IO_EXTENT, dev->name ) - && sbni_probe1( dev, ioaddr, 0 )) + if( request_region( ioaddr, SBNI_IO_EXTENT, dev->name ) && + sbni_probe1( dev, ioaddr, 0 )) return 0; } @@ -287,7 +291,7 @@ static int __init sbni_init(struct net_device *dev) } -int __init +static int __init sbni_pci_probe( struct net_device *dev ) { struct pci_dev *pdev = NULL; @@ -296,20 +300,17 @@ sbni_pci_probe( struct net_device *dev ) != NULL ) { int pci_irq_line; unsigned long pci_ioaddr; - u16 subsys; - if( pdev->vendor != SBNI_PCI_VENDOR - && pdev->device != SBNI_PCI_DEVICE ) - continue; + if( pdev->vendor != SBNI_PCI_VENDOR && + pdev->device != SBNI_PCI_DEVICE ) + continue; pci_ioaddr = pci_resource_start( pdev, 0 ); pci_irq_line = pdev->irq; /* Avoid already found cards from previous calls */ if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) { - pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys ); - - if (subsys != 2) + if (pdev->subsystem_device != 2) continue; /* Dual adapter is present */ @@ -318,12 +319,10 @@ sbni_pci_probe( struct net_device *dev ) continue; } - if( pci_irq_line <= 0 || pci_irq_line >= NR_IRQS ) - printk( KERN_WARNING " WARNING: The PCI BIOS assigned " - "this PCI card to IRQ %d, which is unlikely " - "to work!.\n" - KERN_WARNING " You should use the PCI BIOS " - "setup to assign a valid IRQ line.\n", + if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs) + pr_warn( +"WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n" +"You should use the PCI BIOS setup to assign a valid IRQ line.\n", pci_irq_line ); /* avoiding re-enable dual adapters */ @@ -367,8 +366,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) outb( 0, ioaddr + CSR0 ); if( !irq ) { - printk( KERN_ERR "%s: can't detect device irq!\n", - dev->name ); + pr_err("%s: can't detect device irq!\n", dev->name); release_region( ioaddr, SBNI_IO_EXTENT ); return NULL; } @@ -378,22 +376,23 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) dev->irq = irq; dev->base_addr = ioaddr; - /* Allocate dev->priv and fill in sbni-specific dev fields. */ - nl = dev->priv; + /* Fill in sbni-specific dev fields. */ + nl = netdev_priv(dev); if( !nl ) { - printk( KERN_ERR "%s: unable to get memory!\n", dev->name ); + pr_err("%s: unable to get memory!\n", dev->name); release_region( ioaddr, SBNI_IO_EXTENT ); return NULL; } - dev->priv = nl; memset( nl, 0, sizeof(struct net_local) ); spin_lock_init( &nl->lock ); /* store MAC address (generate if that isn't known) */ *(__be16 *)dev->dev_addr = htons( 0x00ff ); *(__be32 *)(dev->dev_addr + 2) = htonl( 0x01000000 | - ( (mac[num] ? mac[num] : (u32)((long)dev->priv)) & 0x00ffffff) ); + ((mac[num] ? + mac[num] : + (u32)((long)netdev_priv(dev))) & 0x00ffffff)); /* store link settings (speed, receive level ) */ nl->maxframe = DEFAULT_FRAME_LEN; @@ -409,21 +408,21 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) if( inb( ioaddr + CSR0 ) & 0x01 ) nl->state |= FL_SLOW_MODE; - printk( KERN_NOTICE "%s: ioaddr %#lx, irq %d, " - "MAC: 00:ff:01:%02x:%02x:%02x\n", - dev->name, dev->base_addr, dev->irq, - ((u8 *) dev->dev_addr) [3], - ((u8 *) dev->dev_addr) [4], - ((u8 *) dev->dev_addr) [5] ); + pr_notice("%s: ioaddr %#lx, irq %d, MAC: 00:ff:01:%02x:%02x:%02x\n", + dev->name, dev->base_addr, dev->irq, + ((u8 *)dev->dev_addr)[3], + ((u8 *)dev->dev_addr)[4], + ((u8 *)dev->dev_addr)[5]); - printk( KERN_NOTICE "%s: speed %d, receive level ", dev->name, - ( (nl->state & FL_SLOW_MODE) ? 500000 : 2000000) - / (1 << nl->csr1.rate) ); + pr_notice("%s: speed %d", + dev->name, + ((nl->state & FL_SLOW_MODE) ? 500000 : 2000000) + / (1 << nl->csr1.rate)); if( nl->delta_rxl == 0 ) - printk( "0x%x (fixed)\n", nl->cur_rxl_index ); + pr_cont(", receive level 0x%x (fixed)\n", nl->cur_rxl_index); else - printk( "(auto)\n"); + pr_cont(", receive level (auto)\n"); #ifdef CONFIG_SBNI_MULTILINE nl->master = dev; @@ -438,7 +437,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) #ifdef CONFIG_SBNI_MULTILINE -static int +static netdev_tx_t sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) { struct net_device *p; @@ -447,7 +446,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) /* Looking for idle device in the list */ for( p = dev; p; ) { - struct net_local *nl = (struct net_local *) p->priv; + struct net_local *nl = netdev_priv(p); spin_lock( &nl->lock ); if( nl->tx_buf_p || (nl->state & FL_LINE_DOWN) ) { p = nl->link; @@ -457,19 +456,19 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) prepare_to_send( skb, p ); spin_unlock( &nl->lock ); netif_start_queue( dev ); - return 0; + return NETDEV_TX_OK; } } - return 1; + return NETDEV_TX_BUSY; } #else /* CONFIG_SBNI_MULTILINE */ -static int +static netdev_tx_t sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); netif_stop_queue( dev ); spin_lock( &nl->lock ); @@ -477,7 +476,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) prepare_to_send( skb, dev ); spin_unlock( &nl->lock ); - return 0; + return NETDEV_TX_OK; } #endif /* CONFIG_SBNI_MULTILINE */ @@ -503,12 +502,12 @@ static irqreturn_t sbni_interrupt( int irq, void *dev_id ) { struct net_device *dev = dev_id; - struct net_local *nl = dev->priv; + struct net_local *nl = netdev_priv(dev); int repeat; spin_lock( &nl->lock ); if( nl->second ) - spin_lock( &((struct net_local *) nl->second->priv)->lock ); + spin_lock(&NET_LOCAL_LOCK(nl->second)); do { repeat = 0; @@ -522,7 +521,7 @@ sbni_interrupt( int irq, void *dev_id ) } while( repeat ); if( nl->second ) - spin_unlock( &((struct net_local *)nl->second->priv)->lock ); + spin_unlock(&NET_LOCAL_LOCK(nl->second)); spin_unlock( &nl->lock ); return IRQ_HANDLED; } @@ -531,7 +530,7 @@ sbni_interrupt( int irq, void *dev_id ) static void handle_channel( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; int req_ans; @@ -540,7 +539,7 @@ handle_channel( struct net_device *dev ) #ifdef CONFIG_SBNI_MULTILINE /* Lock the master device because we going to change its local data */ if( nl->state & FL_SLAVE ) - spin_lock( &((struct net_local *) nl->master->priv)->lock ); + spin_lock(&NET_LOCAL_LOCK(nl->master)); #endif outb( (inb( ioaddr + CSR0 ) & ~EN_INT) | TR_REQ, ioaddr + CSR0 ); @@ -562,7 +561,7 @@ handle_channel( struct net_device *dev ) */ csr0 = inb( ioaddr + CSR0 ); if( !(csr0 & TR_RDY) || (csr0 & RC_RDY) ) - printk( KERN_ERR "%s: internal error!\n", dev->name ); + netdev_err(dev, "internal error!\n"); /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */ if( req_ans || nl->tx_frameno != 0 ) @@ -576,7 +575,7 @@ handle_channel( struct net_device *dev ) #ifdef CONFIG_SBNI_MULTILINE if( nl->state & FL_SLAVE ) - spin_unlock( &((struct net_local *) nl->master->priv)->lock ); + spin_unlock(&NET_LOCAL_LOCK(nl->master)); #endif } @@ -589,7 +588,7 @@ handle_channel( struct net_device *dev ) static int recv_frame( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; u32 crc = CRC32_INITIAL; @@ -623,7 +622,7 @@ recv_frame( struct net_device *dev ) static void send_frame( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); u32 crc = CRC32_INITIAL; @@ -680,7 +679,7 @@ do_send: static void download_data( struct net_device *dev, u32 *crc_p ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); struct sk_buff *skb = nl->tx_buf_p; unsigned len = min_t(unsigned int, skb->len - nl->outpos, nl->framelen); @@ -699,7 +698,7 @@ static int upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, unsigned is_first, u32 crc ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); int frame_ok; @@ -721,13 +720,11 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, nl->wait_frameno = 0, nl->inppos = 0, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *) nl->master->priv) - ->stats.rx_errors++, - ((struct net_local *) nl->master->priv) - ->stats.rx_missed_errors++; + nl->master->stats.rx_errors++, + nl->master->stats.rx_missed_errors++; #else - nl->stats.rx_errors++, - nl->stats.rx_missed_errors++; + dev->stats.rx_errors++, + dev->stats.rx_missed_errors++; #endif /* now skip all frames until is_first != 0 */ } else @@ -740,11 +737,11 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, */ nl->wait_frameno = 0, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *) nl->master->priv)->stats.rx_errors++, - ((struct net_local *) nl->master->priv)->stats.rx_crc_errors++; + nl->master->stats.rx_errors++, + nl->master->stats.rx_crc_errors++; #else - nl->stats.rx_errors++, - nl->stats.rx_crc_errors++; + dev->stats.rx_errors++, + dev->stats.rx_crc_errors++; #endif return frame_ok; @@ -752,15 +749,16 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, static inline void -send_complete( struct net_local *nl ) +send_complete( struct net_device *dev ) { + struct net_local *nl = netdev_priv(dev); + #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *) nl->master->priv)->stats.tx_packets++; - ((struct net_local *) nl->master->priv)->stats.tx_bytes - += nl->tx_buf_p->len; + nl->master->stats.tx_packets++; + nl->master->stats.tx_bytes += nl->tx_buf_p->len; #else - nl->stats.tx_packets++; - nl->stats.tx_bytes += nl->tx_buf_p->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += nl->tx_buf_p->len; #endif dev_kfree_skb_irq( nl->tx_buf_p ); @@ -775,7 +773,7 @@ send_complete( struct net_local *nl ) static void interpret_ack( struct net_device *dev, unsigned ack ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); if( ack == FRAME_SENT_OK ) { nl->state &= ~FL_NEED_RESEND; @@ -788,7 +786,7 @@ interpret_ack( struct net_device *dev, unsigned ack ) nl->maxframe, nl->tx_buf_p->len - nl->outpos); else - send_complete( nl ), + send_complete( dev ), #ifdef CONFIG_SBNI_MULTILINE netif_wake_queue( nl->master ); #else @@ -809,7 +807,7 @@ interpret_ack( struct net_device *dev, unsigned ack ) static int append_frame_to_pkt( struct net_device *dev, unsigned framelen, u32 crc ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); u8 *p; @@ -840,13 +838,13 @@ append_frame_to_pkt( struct net_device *dev, unsigned framelen, u32 crc ) static void prepare_to_send( struct sk_buff *skb, struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); unsigned int len; /* nl->tx_buf_p == NULL here! */ if( nl->tx_buf_p ) - printk( KERN_ERR "%s: memory leak!\n", dev->name ); + netdev_err(dev, "memory leak!\n"); nl->outpos = 0; nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND); @@ -856,7 +854,7 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev ) len = SBNI_MIN_LEN; nl->tx_buf_p = skb; - nl->tx_frameno = (len + nl->maxframe - 1) / nl->maxframe; + nl->tx_frameno = DIV_ROUND_UP(len, nl->maxframe); nl->framelen = len < nl->maxframe ? len : nl->maxframe; outb( inb( dev->base_addr + CSR0 ) | TR_REQ, dev->base_addr + CSR0 ); @@ -871,19 +869,17 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev ) static void drop_xmit_queue( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); if( nl->tx_buf_p ) dev_kfree_skb_any( nl->tx_buf_p ), nl->tx_buf_p = NULL, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *) nl->master->priv) - ->stats.tx_errors++, - ((struct net_local *) nl->master->priv) - ->stats.tx_carrier_errors++; + nl->master->stats.tx_errors++, + nl->master->stats.tx_carrier_errors++; #else - nl->stats.tx_errors++, - nl->stats.tx_carrier_errors++; + dev->stats.tx_errors++, + dev->stats.tx_carrier_errors++; #endif nl->tx_frameno = 0; @@ -903,7 +899,7 @@ drop_xmit_queue( struct net_device *dev ) static void send_frame_header( struct net_device *dev, u32 *crc_p ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); u32 crc = *crc_p; u32 len_field = nl->framelen + 6; /* CRC + frameno + reserved */ @@ -973,8 +969,8 @@ check_fhdr( u32 ioaddr, u32 *framelen, u32 *frameno, u32 *ack, *ack = *framelen & FRAME_ACK_MASK; *is_first = (*framelen & FRAME_FIRST) != 0; - if( (*framelen &= FRAME_LEN_MASK) < 6 - || *framelen > SBNI_MAX_FRAME - 3 ) + if( (*framelen &= FRAME_LEN_MASK) < 6 || + *framelen > SBNI_MAX_FRAME - 3 ) return 0; value = inb( ioaddr + DAT ); @@ -1005,7 +1001,7 @@ get_rx_buf( struct net_device *dev ) static void indicate_pkt( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); struct sk_buff *skb = nl->rx_buf_p; skb_put( skb, nl->inppos ); @@ -1013,15 +1009,13 @@ indicate_pkt( struct net_device *dev ) #ifdef CONFIG_SBNI_MULTILINE skb->protocol = eth_type_trans( skb, nl->master ); netif_rx( skb ); - dev->last_rx = jiffies; - ++((struct net_local *) nl->master->priv)->stats.rx_packets; - ((struct net_local *) nl->master->priv)->stats.rx_bytes += nl->inppos; + ++nl->master->stats.rx_packets; + nl->master->stats.rx_bytes += nl->inppos; #else skb->protocol = eth_type_trans( skb, dev ); netif_rx( skb ); - dev->last_rx = jiffies; - ++nl->stats.rx_packets; - nl->stats.rx_bytes += nl->inppos; + ++dev->stats.rx_packets; + dev->stats.rx_bytes += nl->inppos; #endif nl->rx_buf_p = NULL; /* protocol driver will clear this sk_buff */ } @@ -1038,7 +1032,7 @@ static void sbni_watchdog( unsigned long arg ) { struct net_device *dev = (struct net_device *) arg; - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); struct timer_list *w = &nl->watchdog; unsigned long flags; unsigned char csr0; @@ -1091,7 +1085,7 @@ static unsigned char timeout_rxl_tab[] = { static void card_start( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); nl->timer_ticks = CHANGE_LEVEL_START_TICKS; nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND); @@ -1113,7 +1107,7 @@ card_start( struct net_device *dev ) static void change_level( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); if( nl->delta_rxl == 0 ) /* do not auto-negotiate RxL */ return; @@ -1137,7 +1131,7 @@ change_level( struct net_device *dev ) static void timeout_change_level( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); nl->cur_rxl_index = timeout_rxl_tab[ nl->timeout_rxl ]; if( ++nl->timeout_rxl >= 4 ) @@ -1160,7 +1154,7 @@ timeout_change_level( struct net_device *dev ) static int sbni_open( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); struct timer_list *w = &nl->watchdog; /* @@ -1171,30 +1165,29 @@ sbni_open( struct net_device *dev ) if( dev->base_addr < 0x400 ) { /* ISA only */ struct net_device **p = sbni_cards; for( ; *p && p < sbni_cards + SBNI_MAX_NUM_CARDS; ++p ) - if( (*p)->irq == dev->irq - && ((*p)->base_addr == dev->base_addr + 4 - || (*p)->base_addr == dev->base_addr - 4) - && (*p)->flags & IFF_UP ) { + if( (*p)->irq == dev->irq && + ((*p)->base_addr == dev->base_addr + 4 || + (*p)->base_addr == dev->base_addr - 4) && + (*p)->flags & IFF_UP ) { - ((struct net_local *) ((*p)->priv)) + ((struct net_local *) (netdev_priv(*p))) ->second = dev; - printk( KERN_NOTICE "%s: using shared irq " - "with %s\n", dev->name, (*p)->name ); + netdev_notice(dev, "using shared irq with %s\n", + (*p)->name); nl->state |= FL_SECONDARY; goto handler_attached; } } if( request_irq(dev->irq, sbni_interrupt, IRQF_SHARED, dev->name, dev) ) { - printk( KERN_ERR "%s: unable to get IRQ %d.\n", - dev->name, dev->irq ); + netdev_err(dev, "unable to get IRQ %d\n", dev->irq); return -EAGAIN; } handler_attached: spin_lock( &nl->lock ); - memset( &nl->stats, 0, sizeof(struct net_device_stats) ); + memset( &dev->stats, 0, sizeof(struct net_device_stats) ); memset( &nl->in_stats, 0, sizeof(struct sbni_in_stats) ); card_start( dev ); @@ -1216,11 +1209,11 @@ handler_attached: static int sbni_close( struct net_device *dev ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); if( nl->second && nl->second->flags & IFF_UP ) { - printk( KERN_NOTICE "Secondary channel (%s) is active!\n", - nl->second->name ); + netdev_notice(dev, "Secondary channel (%s) is active!\n", + nl->second->name); return -EBUSY; } @@ -1300,7 +1293,7 @@ sbni_card_probe( unsigned long ioaddr ) static int sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) { - struct net_local *nl = (struct net_local *) dev->priv; + struct net_local *nl = netdev_priv(dev); struct sbni_flags flags; int error = 0; @@ -1317,7 +1310,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) break; case SIOCDEVRESINSTATS : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; memset( &nl->in_stats, 0, sizeof(struct sbni_in_stats) ); break; @@ -1334,7 +1327,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) break; case SIOCDEVSHWSTATE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; spin_lock( &nl->lock ); @@ -1355,22 +1348,22 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) #ifdef CONFIG_SBNI_MULTILINE case SIOCDEVENSLAVE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name )) return -EFAULT; slave_dev = dev_get_by_name(&init_net, slave_name ); if( !slave_dev || !(slave_dev->flags & IFF_UP) ) { - printk( KERN_ERR "%s: trying to enslave non-active " - "device %s\n", dev->name, slave_name ); + netdev_err(dev, "trying to enslave non-active device %s\n", + slave_name); return -EPERM; } return enslave( dev, slave_dev ); case SIOCDEVEMANSIPATE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; return emancipate( dev ); @@ -1390,8 +1383,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) static int enslave( struct net_device *dev, struct net_device *slave_dev ) { - struct net_local *nl = (struct net_local *) dev->priv; - struct net_local *snl = (struct net_local *) slave_dev->priv; + struct net_local *nl = netdev_priv(dev); + struct net_local *snl = netdev_priv(slave_dev); if( nl->state & FL_SLAVE ) /* This isn't master or free device */ return -EBUSY; @@ -1410,14 +1403,13 @@ enslave( struct net_device *dev, struct net_device *slave_dev ) /* Summary statistics of MultiLine operation will be stored in master's counters */ - memset( &snl->stats, 0, sizeof(struct net_device_stats) ); + memset( &slave_dev->stats, 0, sizeof(struct net_device_stats) ); netif_stop_queue( slave_dev ); netif_wake_queue( dev ); /* Now we are able to transmit */ spin_unlock( &snl->lock ); spin_unlock( &nl->lock ); - printk( KERN_NOTICE "%s: slave device (%s) attached.\n", - dev->name, slave_dev->name ); + netdev_notice(dev, "slave device (%s) attached\n", slave_dev->name); return 0; } @@ -1425,9 +1417,9 @@ enslave( struct net_device *dev, struct net_device *slave_dev ) static int emancipate( struct net_device *dev ) { - struct net_local *snl = (struct net_local *) dev->priv; + struct net_local *snl = netdev_priv(dev); struct net_device *p = snl->master; - struct net_local *nl = (struct net_local *) p->priv; + struct net_local *nl = netdev_priv(p); if( !(snl->state & FL_SLAVE) ) return -EINVAL; @@ -1438,7 +1430,7 @@ emancipate( struct net_device *dev ) /* exclude from list */ for(;;) { /* must be in list */ - struct net_local *t = (struct net_local *) p->priv; + struct net_local *t = netdev_priv(p); if( t->link == dev ) { t->link = snl->link; break; @@ -1461,14 +1453,6 @@ emancipate( struct net_device *dev ) #endif - -static struct net_device_stats * -sbni_get_stats( struct net_device *dev ) -{ - return &((struct net_local *) dev->priv)->stats; -} - - static void set_multicast_list( struct net_device *dev ) { @@ -1517,17 +1501,18 @@ int __init init_module( void ) } void -cleanup_module( void ) +cleanup_module(void) { - struct net_device *dev; - int num; + int i; - for( num = 0; num < SBNI_MAX_NUM_CARDS; ++num ) - if( (dev = sbni_cards[ num ]) != NULL ) { - unregister_netdev( dev ); - release_region( dev->base_addr, SBNI_IO_EXTENT ); - free_netdev( dev ); + for (i = 0; i < SBNI_MAX_NUM_CARDS; ++i) { + struct net_device *dev = sbni_cards[i]; + if (dev != NULL) { + unregister_netdev(dev); + release_region(dev->base_addr, SBNI_IO_EXTENT); + free_netdev(dev); } + } } #else /* MODULE */ @@ -1553,7 +1538,7 @@ sbni_setup( char *p ) break; } bad_param: - printk( KERN_ERR "Error in sbni kernel parameter!\n" ); + pr_err("Error in sbni kernel parameter!\n"); return 0; } @@ -1563,88 +1548,6 @@ __setup( "sbni=", sbni_setup ); /* -------------------------------------------------------------------------- */ -#ifdef ASM_CRC - -static u32 -calc_crc32( u32 crc, u8 *p, u32 len ) -{ - register u32 _crc; - _crc = crc; - - __asm__ __volatile__ ( - "xorl %%ebx, %%ebx\n" - "movl %2, %%esi\n" - "movl %3, %%ecx\n" - "movl $crc32tab, %%edi\n" - "shrl $2, %%ecx\n" - "jz 1f\n" - - ".align 4\n" - "0:\n" - "movb %%al, %%bl\n" - "movl (%%esi), %%edx\n" - "shrl $8, %%eax\n" - "xorb %%dl, %%bl\n" - "shrl $8, %%edx\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb %%dl, %%bl\n" - "shrl $8, %%edx\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb %%dl, %%bl\n" - "movb %%dh, %%dl\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb %%dl, %%bl\n" - "addl $4, %%esi\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "decl %%ecx\n" - "jnz 0b\n" - - "1:\n" - "movl %3, %%ecx\n" - "andl $3, %%ecx\n" - "jz 2f\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb (%%esi), %%bl\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "decl %%ecx\n" - "jz 2f\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb 1(%%esi), %%bl\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - - "decl %%ecx\n" - "jz 2f\n" - - "movb %%al, %%bl\n" - "shrl $8, %%eax\n" - "xorb 2(%%esi), %%bl\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - "2:\n" - : "=a" (_crc) - : "0" (_crc), "g" (p), "g" (len) - : "bx", "cx", "dx", "si", "di" - ); - - return _crc; -} - -#else /* ASM_CRC */ - static u32 calc_crc32( u32 crc, u8 *p, u32 len ) { @@ -1654,9 +1557,6 @@ calc_crc32( u32 crc, u8 *p, u32 len ) return crc; } -#endif /* ASM_CRC */ - - static u32 crc32tab[] __attribute__ ((aligned(8))) = { 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37, 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E, diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 73e2f278093..cdd45fb8a1f 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -32,6 +32,8 @@ * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> @@ -52,7 +54,6 @@ #include <linux/sdla.h> #include <linux/bitops.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/dma.h> #include <asm/uaccess.h> @@ -178,14 +179,14 @@ static char sdla_byte(struct net_device *dev, int addr) byte = *temp; spin_unlock_irqrestore(&sdla_lock, flags); - return(byte); + return byte; } static void sdla_stop(struct net_device *dev) { struct frad_local *flp; - flp = dev->priv; + flp = netdev_priv(dev); switch(flp->type) { case SDLA_S502A: @@ -212,7 +213,7 @@ static void sdla_start(struct net_device *dev) { struct frad_local *flp; - flp = dev->priv; + flp = netdev_priv(dev); switch(flp->type) { case SDLA_S502A: @@ -267,7 +268,7 @@ static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char r resp = *temp; } } - return(time_before(jiffies, done) ? jiffies - start : -1); + return time_before(jiffies, done) ? jiffies - start : -1; } /* constants for Z80 CPU speed */ @@ -283,13 +284,13 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr) sdla_start(dev); if (sdla_z80_poll(dev, 0, 3*HZ, Z80_READY, 0) < 0) - return(-EIO); + return -EIO; data = LOADER_READY; sdla_write(dev, 0, &data, 1); if ((jiffs = sdla_z80_poll(dev, 0, 8*HZ, Z80_SCC_OK, Z80_SCC_BAD)) < 0) - return(-EIO); + return -EIO; sdla_stop(dev); sdla_read(dev, 0, &data, 1); @@ -297,11 +298,11 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr) if (data == Z80_SCC_BAD) { printk("%s: SCC bad\n", dev->name); - return(-EIO); + return -EIO; } if (data != Z80_SCC_OK) - return(-EINVAL); + return -EINVAL; if (jiffs < 165) ifr->ifr_mtu = SDLA_CPU_16M; @@ -316,7 +317,7 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr) else ifr->ifr_mtu = SDLA_CPU_3M; - return(0); + return 0; } /************************************************ @@ -330,7 +331,7 @@ struct _dlci_stat { short dlci; char flags; -} __attribute__((packed)); +} __packed; struct _frad_stat { @@ -350,24 +351,24 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int case SDLA_RET_MODEM: state = data; if (*state & SDLA_MODEM_DCD_LOW) - printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name); + netdev_info(dev, "Modem DCD unexpectedly low!\n"); if (*state & SDLA_MODEM_CTS_LOW) - printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name); + netdev_info(dev, "Modem CTS unexpectedly low!\n"); /* I should probably do something about this! */ break; case SDLA_RET_CHANNEL_OFF: - printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name); + netdev_info(dev, "Channel became inoperative!\n"); /* same here */ break; case SDLA_RET_CHANNEL_ON: - printk(KERN_INFO "%s: Channel became operative!\n", dev->name); + netdev_info(dev, "Channel became operative!\n"); /* same here */ break; case SDLA_RET_DLCI_STATUS: - printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name); + netdev_info(dev, "Status change reported by Access Node\n"); len /= sizeof(struct _dlci_stat); for(pstatus = data, i=0;i < len;i++,pstatus++) { @@ -382,29 +383,32 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int sprintf(line, "unknown status: %02X", pstatus->flags); state = line; } - printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state); + netdev_info(dev, "DLCI %i: %s\n", + pstatus->dlci, state); /* same here */ } break; case SDLA_RET_DLCI_UNKNOWN: - printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name); + netdev_info(dev, "Received unknown DLCIs:"); len /= sizeof(short); for(pdlci = data,i=0;i < len;i++,pdlci++) - printk(" %i", *pdlci); - printk("\n"); + pr_cont(" %i", *pdlci); + pr_cont("\n"); break; case SDLA_RET_TIMEOUT: - printk(KERN_ERR "%s: Command timed out!\n", dev->name); + netdev_err(dev, "Command timed out!\n"); break; case SDLA_RET_BUF_OVERSIZE: - printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len); + netdev_info(dev, "Bc/CIR overflow, acceptable size is %i\n", + len); break; case SDLA_RET_BUF_TOO_BIG: - printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len); + netdev_info(dev, "Buffer size over specified max of %i\n", + len); break; case SDLA_RET_CHANNEL_INACTIVE: @@ -415,7 +419,8 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int break; default: - printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret); + netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n", + cmd, ret); /* Further processing could be done here */ break; } @@ -432,7 +437,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, int ret, waiting, len; long window; - flp = dev->priv; + flp = netdev_priv(dev); window = flp->type == SDLA_S508 ? SDLA_508_CMD_BUF : SDLA_502_CMD_BUF; cmd_buf = (struct sdla_cmd *)(dev->mem_start + (window & SDLA_ADDR_MASK)); ret = 0; @@ -493,7 +498,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags, if (ret != SDLA_RET_OK) sdla_errors(dev, cmd, dlci, ret, len, &status); - return(ret); + return ret; } /*********************************************** @@ -509,21 +514,21 @@ static int sdla_activate(struct net_device *slave, struct net_device *master) struct frad_local *flp; int i; - flp = slave->priv; + flp = netdev_priv(slave); for(i=0;i<CONFIG_DLCI_MAX;i++) if (flp->master[i] == master) break; if (i == CONFIG_DLCI_MAX) - return(-ENODEV); + return -ENODEV; flp->dlci[i] = abs(flp->dlci[i]); if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE)) sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL); - return(0); + return 0; } static int sdla_deactivate(struct net_device *slave, struct net_device *master) @@ -531,21 +536,21 @@ static int sdla_deactivate(struct net_device *slave, struct net_device *master) struct frad_local *flp; int i; - flp = slave->priv; + flp = netdev_priv(slave); for(i=0;i<CONFIG_DLCI_MAX;i++) if (flp->master[i] == master) break; if (i == CONFIG_DLCI_MAX) - return(-ENODEV); + return -ENODEV; flp->dlci[i] = -abs(flp->dlci[i]); if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE)) sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL); - return(0); + return 0; } static int sdla_assoc(struct net_device *slave, struct net_device *master) @@ -554,20 +559,20 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master) int i; if (master->type != ARPHRD_DLCI) - return(-EINVAL); + return -EINVAL; - flp = slave->priv; + flp = netdev_priv(slave); for(i=0;i<CONFIG_DLCI_MAX;i++) { if (!flp->master[i]) break; if (abs(flp->dlci[i]) == *(short *)(master->dev_addr)) - return(-EADDRINUSE); + return -EADDRINUSE; } if (i == CONFIG_DLCI_MAX) - return(-EMLINK); /* #### Alan: Comments on this ?? */ + return -EMLINK; /* #### Alan: Comments on this ?? */ flp->master[i] = master; @@ -581,7 +586,7 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master) sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL); } - return(0); + return 0; } static int sdla_deassoc(struct net_device *slave, struct net_device *master) @@ -589,14 +594,14 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master) struct frad_local *flp; int i; - flp = slave->priv; + flp = netdev_priv(slave); for(i=0;i<CONFIG_DLCI_MAX;i++) if (flp->master[i] == master) break; if (i == CONFIG_DLCI_MAX) - return(-ENODEV); + return -ENODEV; flp->master[i] = NULL; flp->dlci[i] = 0; @@ -609,7 +614,7 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master) sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL); } - return(0); + return 0; } static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get) @@ -619,16 +624,16 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i int i; short len, ret; - flp = slave->priv; + flp = netdev_priv(slave); for(i=0;i<CONFIG_DLCI_MAX;i++) if (flp->master[i] == master) break; if (i == CONFIG_DLCI_MAX) - return(-ENODEV); + return -ENODEV; - dlp = master->priv; + dlp = netdev_priv(master); ret = SDLA_RET_OK; len = sizeof(struct dlci_conf); @@ -641,7 +646,7 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i &dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL); } - return(ret == SDLA_RET_OK ? 0 : -EIO); + return ret == SDLA_RET_OK ? 0 : -EIO; } /************************** @@ -651,7 +656,8 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i **************************/ /* NOTE: the DLCI driver deals with freeing the SKB!! */ -static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t sdla_transmit(struct sk_buff *skb, + struct net_device *dev) { struct frad_local *flp; int ret, addr, accept, i; @@ -659,7 +665,7 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; struct buf_entry *pbuf; - flp = dev->priv; + flp = netdev_priv(dev); ret = 0; accept = 1; @@ -677,12 +683,14 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) case ARPHRD_FRAD: if (skb->dev->type != ARPHRD_DLCI) { - printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type); + netdev_warn(dev, "Non DLCI device, type %i, tried to send on FRAD module\n", + skb->dev->type); accept = 0; } break; default: - printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type); + netdev_warn(dev, "unknown firmware type 0x%04X\n", + dev->type); accept = 0; break; } @@ -711,23 +719,21 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) } break; } + switch (ret) { case SDLA_RET_OK: - flp->stats.tx_packets++; - ret = DLCI_RET_OK; + dev->stats.tx_packets++; break; case SDLA_RET_CIR_OVERFLOW: case SDLA_RET_BUF_OVERSIZE: case SDLA_RET_NO_BUFS: - flp->stats.tx_dropped++; - ret = DLCI_RET_DROP; + dev->stats.tx_dropped++; break; default: - flp->stats.tx_errors++; - ret = DLCI_RET_ERR; + dev->stats.tx_errors++; break; } } @@ -737,7 +743,9 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) if(flp->master[i]!=NULL) netif_wake_queue(flp->master[i]); } - return(ret); + + dev_kfree_skb(skb); + return NETDEV_TX_OK; } static void sdla_receive(struct net_device *dev) @@ -755,7 +763,7 @@ static void sdla_receive(struct net_device *dev) int i=0, received, success, addr, buf_base, buf_top; short dlci, len, len2, split; - flp = dev->priv; + flp = netdev_priv(dev); success = 1; received = addr = buf_top = buf_base = 0; len = dlci = 0; @@ -806,8 +814,9 @@ static void sdla_receive(struct net_device *dev) if (i == CONFIG_DLCI_MAX) { - printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci); - flp->stats.rx_errors++; + netdev_notice(dev, "Received packet from invalid DLCI %i, ignoring\n", + dlci); + dev->stats.rx_errors++; success = 0; } } @@ -818,8 +827,8 @@ static void sdla_receive(struct net_device *dev) skb = dev_alloc_skb(len + sizeof(struct frhdr)); if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - flp->stats.rx_dropped++; + netdev_notice(dev, "Memory squeeze, dropping packet\n"); + dev->stats.rx_dropped++; success = 0; } else @@ -859,8 +868,8 @@ static void sdla_receive(struct net_device *dev) if (success) { - flp->stats.rx_packets++; - dlp = master->priv; + dev->stats.rx_packets++; + dlp = netdev_priv(master); (*dlp->receive)(skb, master); } @@ -879,8 +888,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id) if (!flp->initialized) { - printk(KERN_WARNING "%s: irq %d for uninitialized device.\n", - dev->name, dev->irq); + netdev_warn(dev, "irq %d for uninitialized device\n", dev->irq); return IRQ_NONE; } @@ -900,7 +908,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id) case SDLA_INTR_TX: case SDLA_INTR_COMPLETE: case SDLA_INTR_TIMER: - printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte); + netdev_warn(dev, "invalid irq flag 0x%02X\n", byte); break; } @@ -925,7 +933,7 @@ static void sdla_poll(unsigned long device) struct frad_local *flp; dev = (struct net_device *) device; - flp = dev->priv; + flp = netdev_priv(dev); if (sdla_byte(dev, SDLA_502_RCV_BUF)) sdla_receive(dev); @@ -941,7 +949,7 @@ static int sdla_close(struct net_device *dev) int len, i; short dlcis[CONFIG_DLCI_MAX]; - flp = dev->priv; + flp = netdev_priv(dev); len = 0; for(i=0;i<CONFIG_DLCI_MAX;i++) @@ -985,7 +993,7 @@ static int sdla_close(struct net_device *dev) netif_stop_queue(dev); - return(0); + return 0; } struct conf_data { @@ -1002,13 +1010,13 @@ static int sdla_open(struct net_device *dev) int len, i; char byte; - flp = dev->priv; + flp = netdev_priv(dev); if (!flp->initialized) - return(-EPERM); + return -EPERM; if (!flp->configured) - return(-EPERM); + return -EPERM; /* time to send in the configuration */ len = 0; @@ -1079,14 +1087,14 @@ static int sdla_open(struct net_device *dev) for(i=0;i<CONFIG_DLCI_MAX;i++) if (flp->dlci[i]) { - dlp = flp->master[i]->priv; + dlp = netdev_priv(flp->master[i]); if (dlp->configured) sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL); } netif_start_queue(dev); - return(0); + return 0; } static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get) @@ -1097,48 +1105,48 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in short size; if (dev->type == 0xFFFF) - return(-EUNATCH); + return -EUNATCH; - flp = dev->priv; + flp = netdev_priv(dev); if (!get) { if (netif_running(dev)) - return(-EBUSY); + return -EBUSY; if(copy_from_user(&data.config, conf, sizeof(struct frad_conf))) return -EFAULT; if (data.config.station & ~FRAD_STATION_NODE) - return(-EINVAL); + return -EINVAL; if (data.config.flags & ~FRAD_VALID_FLAGS) - return(-EINVAL); + return -EINVAL; if ((data.config.kbaud < 0) || ((data.config.kbaud > 128) && (flp->type != SDLA_S508))) - return(-EINVAL); + return -EINVAL; if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232)) - return(-EINVAL); + return -EINVAL; if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU)) - return(-EINVAL); + return -EINVAL; if ((data.config.T391 < 5) || (data.config.T391 > 30)) - return(-EINVAL); + return -EINVAL; if ((data.config.T392 < 5) || (data.config.T392 > 30)) - return(-EINVAL); + return -EINVAL; if ((data.config.N391 < 1) || (data.config.N391 > 255)) - return(-EINVAL); + return -EINVAL; if ((data.config.N392 < 1) || (data.config.N392 > 10)) - return(-EINVAL); + return -EINVAL; if ((data.config.N393 < 1) || (data.config.N393 > 10)) - return(-EINVAL); + return -EINVAL; memcpy(&flp->config, &data.config, sizeof(struct frad_conf)); flp->config.flags |= SDLA_DIRECT_RECV; @@ -1170,7 +1178,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in { size = sizeof(data); if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK) - return(-EIO); + return -EIO; } else if (flp->configured) @@ -1184,7 +1192,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0; } - return(0); + return 0; } static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read) @@ -1199,7 +1207,7 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r { temp = kzalloc(mem.len, GFP_KERNEL); if (!temp) - return(-ENOMEM); + return -ENOMEM; sdla_read(dev, mem.addr, temp, mem.len); if(copy_to_user(mem.data, temp, mem.len)) { @@ -1210,18 +1218,13 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r } else { - temp = kmalloc(mem.len, GFP_KERNEL); - if (!temp) - return(-ENOMEM); - if(copy_from_user(temp, mem.data, mem.len)) - { - kfree(temp); - return -EFAULT; - } + temp = memdup_user(mem.data, mem.len); + if (IS_ERR(temp)) + return PTR_ERR(temp); sdla_write(dev, mem.addr, temp, mem.len); kfree(temp); } - return(0); + return 0; } static int sdla_reconfig(struct net_device *dev) @@ -1230,7 +1233,7 @@ static int sdla_reconfig(struct net_device *dev) struct conf_data data; int i, len; - flp = dev->priv; + flp = netdev_priv(dev); len = 0; for(i=0;i<CONFIG_DLCI_MAX;i++) @@ -1245,7 +1248,7 @@ static int sdla_reconfig(struct net_device *dev) sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL); sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL); - return(0); + return 0; } static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -1255,23 +1258,23 @@ static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if(!capable(CAP_NET_ADMIN)) return -EPERM; - flp = dev->priv; + flp = netdev_priv(dev); if (!flp->initialized) - return(-EINVAL); + return -EINVAL; switch (cmd) { case FRAD_GET_CONF: case FRAD_SET_CONF: - return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF)); + return sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF); case SDLA_IDENTIFY: ifr->ifr_flags = flp->type; break; case SDLA_CPUSPEED: - return(sdla_cpuspeed(dev, ifr)); + return sdla_cpuspeed(dev, ifr); /* ========================================================== NOTE: This is rather a useless action right now, as the @@ -1281,7 +1284,7 @@ NOTE: This is rather a useless action right now, as the ============================================================*/ case SDLA_PROTOCOL: if (flp->configured) - return(-EALREADY); + return -EALREADY; switch (ifr->ifr_flags) { @@ -1289,7 +1292,7 @@ NOTE: This is rather a useless action right now, as the dev->type = ifr->ifr_flags; break; default: - return(-ENOPROTOOPT); + return -ENOPROTOOPT; } break; @@ -1301,7 +1304,7 @@ NOTE: This is rather a useless action right now, as the case SDLA_READMEM: if(!capable(CAP_SYS_RAWIO)) return -EPERM; - return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM)); + return sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM); case SDLA_START: sdla_start(dev); @@ -1312,22 +1315,18 @@ NOTE: This is rather a useless action right now, as the break; default: - return(-EOPNOTSUPP); + return -EOPNOTSUPP; } - return(0); + return 0; } static int sdla_change_mtu(struct net_device *dev, int new_mtu) { - struct frad_local *flp; - - flp = dev->priv; - if (netif_running(dev)) - return(-EBUSY); + return -EBUSY; /* for now, you can't change the MTU! */ - return(-EOPNOTSUPP); + return -EOPNOTSUPP; } static int sdla_set_config(struct net_device *dev, struct ifmap *map) @@ -1338,21 +1337,21 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map) unsigned base; int err = -EINVAL; - flp = dev->priv; + flp = netdev_priv(dev); if (flp->initialized) - return(-EINVAL); + return -EINVAL; for(i=0; i < ARRAY_SIZE(valid_port); i++) if (valid_port[i] == map->base_addr) break; if (i == ARRAY_SIZE(valid_port)) - return(-EINVAL); + return -EINVAL; if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ - printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr); - return(-EINVAL); + pr_warn("io-port 0x%04lx in use\n", dev->base_addr); + return -EINVAL; } base = map->base_addr; @@ -1416,7 +1415,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map) } } - printk(KERN_NOTICE "%s: Unknown card type\n", dev->name); + netdev_notice(dev, "Unknown card type\n"); err = -ENODEV; goto fail; @@ -1456,7 +1455,7 @@ got_type: } err = -EAGAIN; - if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) + if (request_irq(dev->irq, sdla_isr, 0, dev->name, dev)) goto fail; if (flp->type == SDLA_S507) { @@ -1590,34 +1589,28 @@ fail: return err; } -static struct net_device_stats *sdla_stats(struct net_device *dev) -{ - struct frad_local *flp; - flp = dev->priv; - - return(&flp->stats); -} +static const struct net_device_ops sdla_netdev_ops = { + .ndo_open = sdla_open, + .ndo_stop = sdla_close, + .ndo_do_ioctl = sdla_ioctl, + .ndo_set_config = sdla_set_config, + .ndo_start_xmit = sdla_transmit, + .ndo_change_mtu = sdla_change_mtu, +}; static void setup_sdla(struct net_device *dev) { - struct frad_local *flp = dev->priv; + struct frad_local *flp = netdev_priv(dev); netdev_boot_setup_check(dev); + dev->netdev_ops = &sdla_netdev_ops; dev->flags = 0; dev->type = 0xFFFF; dev->hard_header_len = 0; dev->addr_len = 0; dev->mtu = SDLA_MAX_MTU; - dev->open = sdla_open; - dev->stop = sdla_close; - dev->do_ioctl = sdla_ioctl; - dev->set_config = sdla_set_config; - dev->get_stats = sdla_stats; - dev->hard_start_xmit = sdla_transmit; - dev->change_mtu = sdla_change_mtu; - flp->activate = sdla_activate; flp->deactivate = sdla_deactivate; flp->assoc = sdla_assoc; @@ -1651,7 +1644,7 @@ static int __init init_sdla(void) static void __exit exit_sdla(void) { - struct frad_local *flp = sdla->priv; + struct frad_local *flp = netdev_priv(sdla); unregister_netdev(sdla); if (flp->initialized) { diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 11276bf3149..27860b4f590 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -8,9 +8,12 @@ * * (c) Copyright 1999, 2001 Alan Cox * (c) Copyright 2001 Red Hat Inc. + * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -19,30 +22,29 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/delay.h> +#include <linux/hdlc.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/slab.h> #include <net/arp.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/dma.h> #include <asm/byteorder.h> -#include <net/syncppp.h> #include "z85230.h" struct slvl_device { - void *if_ptr; /* General purpose pointer (used by SPPP) */ struct z8530_channel *chan; - struct ppp_device pppdev; int channel; }; struct slvl_board { - struct slvl_device *dev[2]; + struct slvl_device dev[2]; struct z8530_dev board; int iobase; }; @@ -51,72 +53,67 @@ struct slvl_board * Network driver support routines */ +static inline struct slvl_device* dev_to_chan(struct net_device *dev) +{ + return (struct slvl_device *)dev_to_hdlc(dev)->priv; +} + /* - * Frame receive. Simple for our card as we do sync ppp and there + * Frame receive. Simple for our card as we do HDLC and there * is no funny garbage involved */ - + static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb) { /* Drop the CRC - it's not a good idea to try and negotiate it ;) */ - skb_trim(skb, skb->len-2); - skb->protocol=htons(ETH_P_WAN_PPP); + skb_trim(skb, skb->len - 2); + skb->protocol = hdlc_type_trans(skb, c->netdevice); skb_reset_mac_header(skb); - skb->dev=c->netdevice; - /* - * Send it to the PPP layer. We don't have time to process - * it right now. - */ + skb->dev = c->netdevice; netif_rx(skb); - c->netdevice->last_rx = jiffies; } - + /* * We've been placed in the UP state - */ - + */ + static int sealevel_open(struct net_device *d) { - struct slvl_device *slvl=d->priv; + struct slvl_device *slvl = dev_to_chan(d); int err = -1; int unit = slvl->channel; - + /* - * Link layer up. + * Link layer up. */ - switch(unit) - { + switch (unit) { case 0: - err=z8530_sync_dma_open(d, slvl->chan); + err = z8530_sync_dma_open(d, slvl->chan); break; case 1: - err=z8530_sync_open(d, slvl->chan); + err = z8530_sync_open(d, slvl->chan); break; } - - if(err) + + if (err) return err; - /* - * Begin PPP - */ - err=sppp_open(d); - if(err) - { - switch(unit) - { + + err = hdlc_open(d); + if (err) { + switch (unit) { case 0: z8530_sync_dma_close(d, slvl->chan); break; case 1: z8530_sync_close(d, slvl->chan); break; - } + } return err; } - - slvl->chan->rx_function=sealevel_input; - + + slvl->chan->rx_function = sealevel_input; + /* * Go go go */ @@ -126,27 +123,19 @@ static int sealevel_open(struct net_device *d) static int sealevel_close(struct net_device *d) { - struct slvl_device *slvl=d->priv; + struct slvl_device *slvl = dev_to_chan(d); int unit = slvl->channel; - + /* * Discard new frames */ - - slvl->chan->rx_function=z8530_null_rx; - - /* - * PPP off - */ - sppp_close(d); - /* - * Link layer down - */ + slvl->chan->rx_function = z8530_null_rx; + + hdlc_close(d); netif_stop_queue(d); - - switch(unit) - { + + switch (unit) { case 0: z8530_sync_dma_close(d, slvl->chan); break; @@ -159,209 +148,159 @@ static int sealevel_close(struct net_device *d) static int sealevel_ioctl(struct net_device *d, struct ifreq *ifr, int cmd) { - /* struct slvl_device *slvl=d->priv; + /* struct slvl_device *slvl=dev_to_chan(d); z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */ - return sppp_do_ioctl(d, ifr,cmd); -} - -static struct net_device_stats *sealevel_get_stats(struct net_device *d) -{ - struct slvl_device *slvl=d->priv; - if(slvl) - return z8530_get_stats(slvl->chan); - else - return NULL; + return hdlc_ioctl(d, ifr, cmd); } /* - * Passed PPP frames, fire them downwind. + * Passed network frames, fire them downwind. */ - -static int sealevel_queue_xmit(struct sk_buff *skb, struct net_device *d) -{ - struct slvl_device *slvl=d->priv; - return z8530_queue_xmit(slvl->chan, skb); -} -static int sealevel_neigh_setup(struct neighbour *n) +static netdev_tx_t sealevel_queue_xmit(struct sk_buff *skb, + struct net_device *d) { - if (n->nud_state == NUD_NONE) { - n->ops = &arp_broken_ops; - n->output = n->ops->output; - } - return 0; + return z8530_queue_xmit(dev_to_chan(d)->chan, skb); } -static int sealevel_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) +static int sealevel_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - if (p->tbl->family == AF_INET) { - p->neigh_setup = sealevel_neigh_setup; - p->ucast_probes = 0; - p->mcast_probes = 0; - } - return 0; + if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT) + return 0; + return -EINVAL; } -static int sealevel_attach(struct net_device *dev) -{ - struct slvl_device *sv = dev->priv; - sppp_attach(&sv->pppdev); - return 0; -} - -static void sealevel_detach(struct net_device *dev) -{ - sppp_detach(dev); -} - -static void slvl_setup(struct net_device *d) -{ - d->open = sealevel_open; - d->stop = sealevel_close; - d->init = sealevel_attach; - d->uninit = sealevel_detach; - d->hard_start_xmit = sealevel_queue_xmit; - d->get_stats = sealevel_get_stats; - d->set_multicast_list = NULL; - d->do_ioctl = sealevel_ioctl; - d->neigh_setup = sealevel_neigh_setup_dev; - d->set_mac_address = NULL; - -} +static const struct net_device_ops sealevel_ops = { + .ndo_open = sealevel_open, + .ndo_stop = sealevel_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = sealevel_ioctl, +}; -static inline struct slvl_device *slvl_alloc(int iobase, int irq) +static int slvl_setup(struct slvl_device *sv, int iobase, int irq) { - struct net_device *d; - struct slvl_device *sv; - - d = alloc_netdev(sizeof(struct slvl_device), "hdlc%d", - slvl_setup); - - if (!d) - return NULL; + struct net_device *dev = alloc_hdlcdev(sv); + if (!dev) + return -1; + + dev_to_hdlc(dev)->attach = sealevel_attach; + dev_to_hdlc(dev)->xmit = sealevel_queue_xmit; + dev->netdev_ops = &sealevel_ops; + dev->base_addr = iobase; + dev->irq = irq; + + if (register_hdlc_device(dev)) { + pr_err("unable to register HDLC device\n"); + free_netdev(dev); + return -1; + } - sv = d->priv; - sv->if_ptr = &sv->pppdev; - sv->pppdev.dev = d; - d->base_addr = iobase; - d->irq = irq; - - return sv; + sv->chan->netdevice = dev; + return 0; } /* * Allocate and setup Sealevel board. */ - -static __init struct slvl_board *slvl_init(int iobase, int irq, + +static __init struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow) { struct z8530_dev *dev; struct slvl_board *b; - + /* * Get the needed I/O space */ - if(!request_region(iobase, 8, "Sealevel 4021")) - { - printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase); + if (!request_region(iobase, 8, "Sealevel 4021")) { + pr_warn("I/O 0x%X already in use\n", iobase); return NULL; } - - b = kzalloc(sizeof(struct slvl_board), GFP_KERNEL); - if(!b) - goto fail3; - if (!(b->dev[0]= slvl_alloc(iobase, irq))) - goto fail2; + b = kzalloc(sizeof(struct slvl_board), GFP_KERNEL); + if (!b) + goto err_kzalloc; - b->dev[0]->chan = &b->board.chanA; - b->dev[0]->channel = 0; - - if (!(b->dev[1] = slvl_alloc(iobase, irq))) - goto fail1_0; + b->dev[0].chan = &b->board.chanA; + b->dev[0].channel = 0; - b->dev[1]->chan = &b->board.chanB; - b->dev[1]->channel = 1; + b->dev[1].chan = &b->board.chanB; + b->dev[1].channel = 1; dev = &b->board; - + /* * Stuff in the I/O addressing */ - + dev->active = 0; b->iobase = iobase; - + /* * Select 8530 delays for the old board */ - - if(slow) + + if (slow) iobase |= Z8530_PORT_SLEEP; - - dev->chanA.ctrlio=iobase+1; - dev->chanA.dataio=iobase; - dev->chanB.ctrlio=iobase+3; - dev->chanB.dataio=iobase+2; - - dev->chanA.irqs=&z8530_nop; - dev->chanB.irqs=&z8530_nop; - + + dev->chanA.ctrlio = iobase + 1; + dev->chanA.dataio = iobase; + dev->chanB.ctrlio = iobase + 3; + dev->chanB.dataio = iobase + 2; + + dev->chanA.irqs = &z8530_nop; + dev->chanB.irqs = &z8530_nop; + /* * Assert DTR enable DMA */ - - outb(3|(1<<7), b->iobase+4); - + + outb(3 | (1 << 7), b->iobase + 4); + /* We want a fast IRQ for this device. Actually we'd like an even faster IRQ ;) - This is one driver RtLinux is made for */ - - if(request_irq(irq, &z8530_interrupt, IRQF_DISABLED, "SeaLevel", dev)<0) - { - printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq); - goto fail1_1; + + if (request_irq(irq, z8530_interrupt, 0, + "SeaLevel", dev) < 0) { + pr_warn("IRQ %d already in use\n", irq); + goto err_request_irq; } - - dev->irq=irq; - dev->chanA.private=&b->dev[0]; - dev->chanB.private=&b->dev[1]; - dev->chanA.netdevice=b->dev[0]->pppdev.dev; - dev->chanB.netdevice=b->dev[1]->pppdev.dev; - dev->chanA.dev=dev; - dev->chanB.dev=dev; - - dev->chanA.txdma=3; - dev->chanA.rxdma=1; - if(request_dma(dev->chanA.txdma, "SeaLevel (TX)")!=0) - goto fail; - - if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0) - goto dmafail; - + + dev->irq = irq; + dev->chanA.private = &b->dev[0]; + dev->chanB.private = &b->dev[1]; + dev->chanA.dev = dev; + dev->chanB.dev = dev; + + dev->chanA.txdma = 3; + dev->chanA.rxdma = 1; + if (request_dma(dev->chanA.txdma, "SeaLevel (TX)")) + goto err_dma_tx; + + if (request_dma(dev->chanA.rxdma, "SeaLevel (RX)")) + goto err_dma_rx; + disable_irq(irq); - + /* * Begin normal initialise */ - - if(z8530_init(dev)!=0) - { - printk(KERN_ERR "Z8530 series device not found.\n"); + + if (z8530_init(dev) != 0) { + pr_err("Z8530 series device not found\n"); enable_irq(irq); - goto dmafail2; + goto free_hw; } - if(dev->type==Z85C30) - { + if (dev->type == Z85C30) { z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream); z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream); - } - else - { + } else { z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230); z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream_85230); } @@ -369,36 +308,31 @@ static __init struct slvl_board *slvl_init(int iobase, int irq, /* * Now we can take the IRQ */ - + enable_irq(irq); - if (register_netdev(b->dev[0]->pppdev.dev)) - goto dmafail2; - - if (register_netdev(b->dev[1]->pppdev.dev)) - goto fail_unit; + if (slvl_setup(&b->dev[0], iobase, irq)) + goto free_hw; + if (slvl_setup(&b->dev[1], iobase, irq)) + goto free_netdev0; z8530_describe(dev, "I/O", iobase); - dev->active=1; + dev->active = 1; return b; -fail_unit: - unregister_netdev(b->dev[0]->pppdev.dev); - -dmafail2: +free_netdev0: + unregister_hdlc_device(b->dev[0].chan->netdevice); + free_netdev(b->dev[0].chan->netdevice); +free_hw: free_dma(dev->chanA.rxdma); -dmafail: +err_dma_rx: free_dma(dev->chanA.txdma); -fail: +err_dma_tx: free_irq(irq, dev); -fail1_1: - free_netdev(b->dev[1]->pppdev.dev); -fail1_0: - free_netdev(b->dev[0]->pppdev.dev); -fail2: +err_request_irq: kfree(b); -fail3: - release_region(iobase,8); +err_kzalloc: + release_region(iobase, 8); return NULL; } @@ -407,14 +341,13 @@ static void __exit slvl_shutdown(struct slvl_board *b) int u; z8530_shutdown(&b->board); - - for(u=0; u<2; u++) - { - struct net_device *d = b->dev[u]->pppdev.dev; - unregister_netdev(d); + + for (u = 0; u < 2; u++) { + struct net_device *d = b->dev[u].chan->netdevice; + unregister_hdlc_device(d); free_netdev(d); } - + free_irq(b->board.irq, &b->board); free_dma(b->board.chanA.rxdma); free_dma(b->board.chanA.txdma); @@ -429,7 +362,7 @@ static int io=0x238; static int txdma=1; static int rxdma=3; static int irq=5; -static int slow=0; +static bool slow=false; module_param(io, int, 0); MODULE_PARM_DESC(io, "The I/O base of the Sealevel card"); @@ -450,10 +383,6 @@ static struct slvl_board *slvl_unit; static int __init slvl_init_module(void) { -#ifdef MODULE - printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.02.\n"); - printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n"); -#endif slvl_unit = slvl_init(io, irq, txdma, rxdma, slow); return slvl_unit ? 0 : -ENODEV; @@ -461,7 +390,7 @@ static int __init slvl_init_module(void) static void __exit slvl_cleanup_module(void) { - if(slvl_unit) + if (slvl_unit) slvl_shutdown(slvl_unit); } diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c deleted file mode 100644 index 61e24b7a45a..00000000000 --- a/drivers/net/wan/syncppp.c +++ /dev/null @@ -1,1488 +0,0 @@ -/* - * NET3: A (fairly minimal) implementation of synchronous PPP for Linux - * as well as a CISCO HDLC implementation. See the copyright - * message below for the original source. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the license, or (at your option) any later version. - * - * Note however. This code is also used in a different form by FreeBSD. - * Therefore when making any non OS specific change please consider - * contributing it back to the original author under the terms - * below in addition. - * -- Alan - * - * Port for Linux-2.1 by Jan "Yenya" Kasprzak <kas@fi.muni.cz> - */ - -/* - * Synchronous PPP/Cisco link level subroutines. - * Keepalive protocol implemented in both Cisco and PPP modes. - * - * Copyright (C) 1994 Cronyx Ltd. - * Author: Serge Vakulenko, <vak@zebub.msk.su> - * - * This software is distributed with NO WARRANTIES, not even the implied - * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Authors grant any other persons or organisations permission to use - * or modify this software as long as this message is kept with the software, - * all derivative works or modified versions. - * - * Version 1.9, Wed Oct 4 18:58:15 MSK 1995 - * - * $Id: syncppp.c,v 1.18 2000/04/11 05:25:31 asj Exp $ - */ -#undef DEBUG - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/if_arp.h> -#include <linux/skbuff.h> -#include <linux/route.h> -#include <linux/netdevice.h> -#include <linux/inetdevice.h> -#include <linux/random.h> -#include <linux/pkt_sched.h> -#include <linux/spinlock.h> -#include <linux/rcupdate.h> - -#include <net/net_namespace.h> -#include <net/syncppp.h> - -#include <asm/byteorder.h> -#include <asm/uaccess.h> - -#define MAXALIVECNT 6 /* max. alive packets */ - -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_IP 0x0021 /* Internet Protocol */ -#define PPP_ISO 0x0023 /* ISO OSI Protocol */ -#define PPP_XNS 0x0025 /* Xerox NS Protocol */ -#define PPP_IPX 0x002b /* Novell IPX Protocol */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ - -#define LCP_CONF_REQ 1 /* PPP LCP configure request */ -#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */ -#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */ -#define LCP_CONF_REJ 4 /* PPP LCP configure reject */ -#define LCP_TERM_REQ 5 /* PPP LCP terminate request */ -#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */ -#define LCP_CODE_REJ 7 /* PPP LCP code reject */ -#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */ -#define LCP_ECHO_REQ 9 /* PPP LCP echo request */ -#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */ -#define LCP_DISC_REQ 11 /* PPP LCP discard request */ - -#define LCP_OPT_MRU 1 /* maximum receive unit */ -#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ -#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ -#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ -#define LCP_OPT_MAGIC 5 /* magic number */ -#define LCP_OPT_RESERVED 6 /* reserved */ -#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ -#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ - -#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */ -#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */ -#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */ -#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */ -#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */ -#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */ -#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */ - -#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ -#define CISCO_UNICAST 0x0f /* Cisco unicast address */ -#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ -#define CISCO_ADDR_REQ 0 /* Cisco address request */ -#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ -#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ - -struct ppp_header { - u8 address; - u8 control; - __be16 protocol; -}; -#define PPP_HEADER_LEN sizeof (struct ppp_header) - -struct lcp_header { - u8 type; - u8 ident; - __be16 len; -}; -#define LCP_HEADER_LEN sizeof (struct lcp_header) - -struct cisco_packet { - __be32 type; - __be32 par1; - __be32 par2; - __be16 rel; - __be16 time0; - __be16 time1; -}; -#define CISCO_PACKET_LEN 18 -#define CISCO_BIG_PACKET_LEN 20 - -static struct sppp *spppq; -static struct timer_list sppp_keepalive_timer; -static DEFINE_SPINLOCK(spppq_lock); - -/* global xmit queue for sending packets while spinlock is held */ -static struct sk_buff_head tx_queue; - -static void sppp_keepalive (unsigned long dummy); -static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, - u8 ident, u16 len, void *data); -static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2); -static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); -static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); -static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); -static void sppp_lcp_open (struct sppp *sp); -static void sppp_ipcp_open (struct sppp *sp); -static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, - int len, u32 *magic); -static void sppp_cp_timeout (unsigned long arg); -static char *sppp_lcp_type_name (u8 type); -static char *sppp_ipcp_type_name (u8 type); -static void sppp_print_bytes (u8 *p, u16 len); - -static int debug; - -/* Flush global outgoing packet queue to dev_queue_xmit(). - * - * dev_queue_xmit() must be called with interrupts enabled - * which means it can't be called with spinlocks held. - * If a packet needs to be sent while a spinlock is held, - * then put the packet into tx_queue, and call sppp_flush_xmit() - * after spinlock is released. - */ -static void sppp_flush_xmit(void) -{ - struct sk_buff *skb; - while ((skb = skb_dequeue(&tx_queue)) != NULL) - dev_queue_xmit(skb); -} - -/* - * Interface down stub - */ - -static void if_down(struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - - sp->pp_link_state=SPPP_LINK_DOWN; -} - -/* - * Timeout routine activations. - */ - -static void sppp_set_timeout(struct sppp *p,int s) -{ - if (! (p->pp_flags & PP_TIMO)) - { - init_timer(&p->pp_timer); - p->pp_timer.function=sppp_cp_timeout; - p->pp_timer.expires=jiffies+s*HZ; - p->pp_timer.data=(unsigned long)p; - p->pp_flags |= PP_TIMO; - add_timer(&p->pp_timer); - } -} - -static void sppp_clear_timeout(struct sppp *p) -{ - if (p->pp_flags & PP_TIMO) - { - del_timer(&p->pp_timer); - p->pp_flags &= ~PP_TIMO; - } -} - -/** - * sppp_input - receive and process a WAN PPP frame - * @skb: The buffer to process - * @dev: The device it arrived on - * - * This can be called directly by cards that do not have - * timing constraints but is normally called from the network layer - * after interrupt servicing to process frames queued via netif_rx(). - * - * We process the options in the card. If the frame is destined for - * the protocol stacks then it requeues the frame for the upper level - * protocol. If it is a control from it is processed and discarded - * here. - */ - -static void sppp_input (struct net_device *dev, struct sk_buff *skb) -{ - struct ppp_header *h; - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - skb->dev=dev; - skb_reset_mac_header(skb); - - if (dev->flags & IFF_RUNNING) - { - /* Count received bytes, add FCS and one flag */ - sp->ibytes+= skb->len + 3; - sp->ipkts++; - } - - if (!pskb_may_pull(skb, PPP_HEADER_LEN)) { - /* Too small packet, drop it. */ - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", - dev->name, skb->len); - kfree_skb(skb); - return; - } - - /* Get PPP header. */ - h = (struct ppp_header *)skb->data; - skb_pull(skb,sizeof(struct ppp_header)); - - spin_lock_irqsave(&sp->lock, flags); - - switch (h->address) { - default: /* Invalid PPP packet. */ - goto invalid; - case PPP_ALLSTATIONS: - if (h->control != PPP_UI) - goto invalid; - if (sp->pp_flags & PP_CISCO) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - } - switch (ntohs (h->protocol)) { - default: - if (sp->lcp.state == LCP_STATE_OPENED) - sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ, - ++sp->pp_seq, skb->len + 2, - &h->protocol); - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid input protocol <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - case PPP_LCP: - sppp_lcp_input (sp, skb); - goto drop; - case PPP_IPCP: - if (sp->lcp.state == LCP_STATE_OPENED) - sppp_ipcp_input (sp, skb); - else - printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n"); - goto drop; - case PPP_IP: - if (sp->ipcp.state == IPCP_STATE_OPENED) { - if(sp->pp_flags&PP_DEBUG) - printk(KERN_DEBUG "Yow an IP frame.\n"); - skb->protocol=htons(ETH_P_IP); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; - } - break; -#ifdef IPX - case PPP_IPX: - /* IPX IPXCP not implemented yet */ - if (sp->lcp.state == LCP_STATE_OPENED) { - skb->protocol=htons(ETH_P_IPX); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; - } - break; -#endif - } - break; - case CISCO_MULTICAST: - case CISCO_UNICAST: - /* Don't check the control field here (RFC 1547). */ - if (! (sp->pp_flags & PP_CISCO)) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - } - switch (ntohs (h->protocol)) { - default: - goto invalid; - case CISCO_KEEPALIVE: - sppp_cisco_input (sp, skb); - goto drop; -#ifdef CONFIG_INET - case ETH_P_IP: - skb->protocol=htons(ETH_P_IP); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; -#endif -#ifdef CONFIG_IPX - case ETH_P_IPX: - skb->protocol=htons(ETH_P_IPX); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; -#endif - } - break; - } - goto drop; - -invalid: - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", - dev->name, h->address, h->control, ntohs (h->protocol)); -drop: - kfree_skb(skb); -done: - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); - return; -} - -/* - * Handle transmit packets. - */ - -static int sppp_hard_header(struct sk_buff *skb, - struct net_device *dev, __u16 type, - const void *daddr, const void *saddr, - unsigned int len) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - struct ppp_header *h; - skb_push(skb,sizeof(struct ppp_header)); - h=(struct ppp_header *)skb->data; - if(sp->pp_flags&PP_CISCO) - { - h->address = CISCO_UNICAST; - h->control = 0; - } - else - { - h->address = PPP_ALLSTATIONS; - h->control = PPP_UI; - } - if(sp->pp_flags & PP_CISCO) - { - h->protocol = htons(type); - } - else switch(type) - { - case ETH_P_IP: - h->protocol = htons(PPP_IP); - break; - case ETH_P_IPX: - h->protocol = htons(PPP_IPX); - break; - } - return sizeof(struct ppp_header); -} - -static const struct header_ops sppp_header_ops = { - .create = sppp_hard_header, -}; - -/* - * Send keepalive packets, every 10 seconds. - */ - -static void sppp_keepalive (unsigned long dummy) -{ - struct sppp *sp; - unsigned long flags; - - spin_lock_irqsave(&spppq_lock, flags); - - for (sp=spppq; sp; sp=sp->pp_next) - { - struct net_device *dev = sp->pp_if; - - /* Keepalive mode disabled or channel down? */ - if (! (sp->pp_flags & PP_KEEPALIVE) || - ! (dev->flags & IFF_UP)) - continue; - - spin_lock(&sp->lock); - - /* No keepalive in PPP mode if LCP not opened yet. */ - if (! (sp->pp_flags & PP_CISCO) && - sp->lcp.state != LCP_STATE_OPENED) { - spin_unlock(&sp->lock); - continue; - } - - if (sp->pp_alivecnt == MAXALIVECNT) { - /* No keepalive packets got. Stop the interface. */ - printk (KERN_WARNING "%s: protocol down\n", dev->name); - if_down (dev); - if (! (sp->pp_flags & PP_CISCO)) { - /* Shut down the PPP link. */ - sp->lcp.magic = jiffies; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - /* Initiate negotiation. */ - sppp_lcp_open (sp); - } - } - if (sp->pp_alivecnt <= MAXALIVECNT) - ++sp->pp_alivecnt; - if (sp->pp_flags & PP_CISCO) - sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, - sp->pp_rseq); - else if (sp->lcp.state == LCP_STATE_OPENED) { - __be32 nmagic = htonl (sp->lcp.magic); - sp->lcp.echoid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, - sp->lcp.echoid, 4, &nmagic); - } - - spin_unlock(&sp->lock); - } - spin_unlock_irqrestore(&spppq_lock, flags); - sppp_flush_xmit(); - sppp_keepalive_timer.expires=jiffies+10*HZ; - add_timer(&sppp_keepalive_timer); -} - -/* - * Handle incoming PPP Link Control Protocol packets. - */ - -static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) -{ - struct lcp_header *h; - struct net_device *dev = sp->pp_if; - int len = skb->len; - u8 *p, opt[6]; - u32 rmagic = 0; - - if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n", - dev->name, len); - return; - } - h = (struct lcp_header *)skb->data; - skb_pull(skb,sizeof(struct lcp_header *)); - - if (sp->pp_flags & PP_DEBUG) - { - char state = '?'; - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: state = 'C'; break; - case LCP_STATE_ACK_RCVD: state = 'R'; break; - case LCP_STATE_ACK_SENT: state = 'S'; break; - case LCP_STATE_OPENED: state = 'O'; break; - } - printk (KERN_WARNING "%s: lcp input(%c): %d bytes <%s id=%xh len=%xh", - dev->name, state, len, - sppp_lcp_type_name (h->type), h->ident, ntohs (h->len)); - if (len > 4) - sppp_print_bytes ((u8*) (h+1), len-4); - printk (">\n"); - } - if (len > ntohs (h->len)) - len = ntohs (h->len); - switch (h->type) { - default: - /* Unknown packet type -- send Code-Reject packet. */ - sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, - skb->len, h); - break; - case LCP_CONF_REQ: - if (len < 4) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n", - dev->name, len); - break; - } - if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic)) - goto badreq; - if (rmagic == sp->lcp.magic) { - /* Local and remote magics equal -- loopback? */ - if (sp->pp_loopcnt >= MAXALIVECNT*5) { - printk (KERN_WARNING "%s: loopback\n", - dev->name); - sp->pp_loopcnt = 0; - if (dev->flags & IFF_UP) { - if_down (dev); - } - } else if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: conf req: magic glitch\n", - dev->name); - ++sp->pp_loopcnt; - - /* MUST send Conf-Nack packet. */ - rmagic = ~sp->lcp.magic; - opt[0] = LCP_OPT_MAGIC; - opt[1] = sizeof (opt); - opt[2] = rmagic >> 24; - opt[3] = rmagic >> 16; - opt[4] = rmagic >> 8; - opt[5] = rmagic; - sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, - h->ident, sizeof (opt), &opt); -badreq: - switch (sp->lcp.state) { - case LCP_STATE_OPENED: - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - /* fall through... */ - case LCP_STATE_ACK_SENT: - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - break; - } - /* Send Configure-Ack packet. */ - sp->pp_loopcnt = 0; - if (sp->lcp.state != LCP_STATE_OPENED) { - sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, - h->ident, len-4, h+1); - } - /* Change the state. */ - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - sp->lcp.state = LCP_STATE_ACK_SENT; - break; - case LCP_STATE_ACK_RCVD: - sp->lcp.state = LCP_STATE_OPENED; - sppp_ipcp_open (sp); - break; - case LCP_STATE_OPENED: - /* Remote magic changed -- close session. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - /* Send ACK after our REQ in attempt to break loop */ - sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, - h->ident, len-4, h+1); - sp->lcp.state = LCP_STATE_ACK_SENT; - break; - } - break; - case LCP_CONF_ACK: - if (h->ident != sp->lcp.confid) - break; - sppp_clear_timeout (sp); - if ((sp->pp_link_state != SPPP_LINK_UP) && - (dev->flags & IFF_UP)) { - /* Coming out of loopback mode. */ - sp->pp_link_state=SPPP_LINK_UP; - printk (KERN_INFO "%s: protocol up\n", dev->name); - } - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - sp->lcp.state = LCP_STATE_ACK_RCVD; - sppp_set_timeout (sp, 5); - break; - case LCP_STATE_ACK_SENT: - sp->lcp.state = LCP_STATE_OPENED; - sppp_ipcp_open (sp); - break; - } - break; - case LCP_CONF_NAK: - if (h->ident != sp->lcp.confid) - break; - p = (u8*) (h+1); - if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) { - rmagic = (u32)p[2] << 24 | - (u32)p[3] << 16 | p[4] << 8 | p[5]; - if (rmagic == ~sp->lcp.magic) { - int newmagic; - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: conf nak: magic glitch\n", - dev->name); - get_random_bytes(&newmagic, sizeof(newmagic)); - sp->lcp.magic += newmagic; - } else - sp->lcp.magic = rmagic; - } - if (sp->lcp.state != LCP_STATE_ACK_SENT) { - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - /* The link will be renegotiated after timeout, - * to avoid endless req-nack loop. */ - sppp_clear_timeout (sp); - sppp_set_timeout (sp, 2); - break; - case LCP_CONF_REJ: - if (h->ident != sp->lcp.confid) - break; - sppp_clear_timeout (sp); - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - if (sp->lcp.state != LCP_STATE_ACK_SENT) { - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - break; - case LCP_TERM_REQ: - sppp_clear_timeout (sp); - /* Send Terminate-Ack packet. */ - sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL); - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - break; - case LCP_TERM_ACK: - case LCP_CODE_REJ: - case LCP_PROTO_REJ: - /* Ignore for now. */ - break; - case LCP_DISC_REQ: - /* Discard the packet. */ - break; - case LCP_ECHO_REQ: - if (sp->lcp.state != LCP_STATE_OPENED) - break; - if (len < 8) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n", - dev->name, len); - break; - } - if (ntohl (*(__be32*)(h+1)) == sp->lcp.magic) { - /* Line loopback mode detected. */ - printk (KERN_WARNING "%s: loopback\n", dev->name); - if_down (dev); - - /* Shut down the PPP link. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - /* Initiate negotiation. */ - sppp_lcp_open (sp); - break; - } - *(__be32 *)(h+1) = htonl (sp->lcp.magic); - sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); - break; - case LCP_ECHO_REPLY: - if (h->ident != sp->lcp.echoid) - break; - if (len < 8) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n", - dev->name, len); - break; - } - if (ntohl(*(__be32 *)(h+1)) != sp->lcp.magic) - sp->pp_alivecnt = 0; - break; - } -} - -/* - * Handle incoming Cisco keepalive protocol packets. - */ - -static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) -{ - struct cisco_packet *h; - struct net_device *dev = sp->pp_if; - - if (!pskb_may_pull(skb, sizeof(struct cisco_packet)) - || (skb->len != CISCO_PACKET_LEN - && skb->len != CISCO_BIG_PACKET_LEN)) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n", - dev->name, skb->len); - return; - } - h = (struct cisco_packet *)skb->data; - skb_pull(skb, sizeof(struct cisco_packet*)); - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n", - dev->name, skb->len, - ntohl (h->type), h->par1, h->par2, h->rel, - h->time0, h->time1); - switch (ntohl (h->type)) { - default: - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n", - dev->name, ntohl (h->type)); - break; - case CISCO_ADDR_REPLY: - /* Reply on address request, ignore */ - break; - case CISCO_KEEPALIVE_REQ: - sp->pp_alivecnt = 0; - sp->pp_rseq = ntohl (h->par1); - if (sp->pp_seq == sp->pp_rseq) { - /* Local and remote sequence numbers are equal. - * Probably, the line is in loopback mode. */ - int newseq; - if (sp->pp_loopcnt >= MAXALIVECNT) { - printk (KERN_WARNING "%s: loopback\n", - dev->name); - sp->pp_loopcnt = 0; - if (dev->flags & IFF_UP) { - if_down (dev); - } - } - ++sp->pp_loopcnt; - - /* Generate new local sequence number */ - get_random_bytes(&newseq, sizeof(newseq)); - sp->pp_seq ^= newseq; - break; - } - sp->pp_loopcnt = 0; - if (sp->pp_link_state==SPPP_LINK_DOWN && - (dev->flags & IFF_UP)) { - sp->pp_link_state=SPPP_LINK_UP; - printk (KERN_INFO "%s: protocol up\n", dev->name); - } - break; - case CISCO_ADDR_REQ: - /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */ - { - struct in_device *in_dev; - struct in_ifaddr *ifa; - __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */ -#ifdef CONFIG_INET - rcu_read_lock(); - if ((in_dev = __in_dev_get_rcu(dev)) != NULL) - { - for (ifa=in_dev->ifa_list; ifa != NULL; - ifa=ifa->ifa_next) { - if (strcmp(dev->name, ifa->ifa_label) == 0) - { - addr = ifa->ifa_local; - mask = ifa->ifa_mask; - break; - } - } - } - rcu_read_unlock(); -#endif - sppp_cisco_send (sp, CISCO_ADDR_REPLY, ntohl(addr), ntohl(mask)); - break; - } - } -} - - -/* - * Send PPP LCP packet. - */ - -static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, - u8 ident, u16 len, void *data) -{ - struct ppp_header *h; - struct lcp_header *lh; - struct sk_buff *skb; - struct net_device *dev = sp->pp_if; - - skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len, - GFP_ATOMIC); - if (skb==NULL) - return; - - skb_reserve(skb,dev->hard_header_len); - - h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header)); - h->address = PPP_ALLSTATIONS; /* broadcast address */ - h->control = PPP_UI; /* Unnumbered Info */ - h->protocol = htons (proto); /* Link Control Protocol */ - - lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header)); - lh->type = type; - lh->ident = ident; - lh->len = htons (LCP_HEADER_LEN + len); - - if (len) - memcpy(skb_put(skb,len),data, len); - - if (sp->pp_flags & PP_DEBUG) { - printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh", - dev->name, - proto==PPP_LCP ? "lcp" : "ipcp", - proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : - sppp_ipcp_type_name (lh->type), lh->ident, - ntohs (lh->len)); - if (len) - sppp_print_bytes ((u8*) (lh+1), len); - printk (">\n"); - } - sp->obytes += skb->len; - /* Control is high priority so it doesn't get queued behind data */ - skb->priority=TC_PRIO_CONTROL; - skb->dev = dev; - skb_queue_tail(&tx_queue, skb); -} - -/* - * Send Cisco keepalive packet. - */ - -static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2) -{ - struct ppp_header *h; - struct cisco_packet *ch; - struct sk_buff *skb; - struct net_device *dev = sp->pp_if; - u32 t = jiffies * 1000/HZ; - - skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN, - GFP_ATOMIC); - - if(skb==NULL) - return; - - skb_reserve(skb, dev->hard_header_len); - h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header)); - h->address = CISCO_MULTICAST; - h->control = 0; - h->protocol = htons (CISCO_KEEPALIVE); - - ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN); - ch->type = htonl (type); - ch->par1 = htonl (par1); - ch->par2 = htonl (par2); - ch->rel = htons(0xffff); - ch->time0 = htons ((u16) (t >> 16)); - ch->time1 = htons ((u16) t); - - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n", - dev->name, ntohl (ch->type), ch->par1, - ch->par2, ch->rel, ch->time0, ch->time1); - sp->obytes += skb->len; - skb->priority=TC_PRIO_CONTROL; - skb->dev = dev; - skb_queue_tail(&tx_queue, skb); -} - -/** - * sppp_close - close down a synchronous PPP or Cisco HDLC link - * @dev: The network device to drop the link of - * - * This drops the logical interface to the channel. It is not - * done politely as we assume we will also be dropping DTR. Any - * timeouts are killed. - */ - -int sppp_close (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - spin_lock_irqsave(&sp->lock, flags); - sp->pp_link_state = SPPP_LINK_DOWN; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - spin_unlock_irqrestore(&sp->lock, flags); - - return 0; -} - -EXPORT_SYMBOL(sppp_close); - -/** - * sppp_open - open a synchronous PPP or Cisco HDLC link - * @dev: Network device to activate - * - * Close down any existing synchronous session and commence - * from scratch. In the PPP case this means negotiating LCP/IPCP - * and friends, while for Cisco HDLC we simply need to start sending - * keepalives - */ - -int sppp_open (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - sppp_close(dev); - - spin_lock_irqsave(&sp->lock, flags); - if (!(sp->pp_flags & PP_CISCO)) { - sppp_lcp_open (sp); - } - sp->pp_link_state = SPPP_LINK_DOWN; - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); - - return 0; -} - -EXPORT_SYMBOL(sppp_open); - -/** - * sppp_reopen - notify of physical link loss - * @dev: Device that lost the link - * - * This function informs the synchronous protocol code that - * the underlying link died (for example a carrier drop on X.21) - * - * We increment the magic numbers to ensure that if the other end - * failed to notice we will correctly start a new session. It happens - * do to the nature of telco circuits is that you can lose carrier on - * one endonly. - * - * Having done this we go back to negotiating. This function may - * be called from an interrupt context. - */ - -int sppp_reopen (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - sppp_close(dev); - - spin_lock_irqsave(&sp->lock, flags); - if (!(sp->pp_flags & PP_CISCO)) - { - sp->lcp.magic = jiffies; - ++sp->pp_seq; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Give it a moment for the line to settle then go */ - sppp_set_timeout (sp, 1); - } - sp->pp_link_state=SPPP_LINK_DOWN; - spin_unlock_irqrestore(&sp->lock, flags); - - return 0; -} - -EXPORT_SYMBOL(sppp_reopen); - -/** - * sppp_change_mtu - Change the link MTU - * @dev: Device to change MTU on - * @new_mtu: New MTU - * - * Change the MTU on the link. This can only be called with - * the link down. It returns an error if the link is up or - * the mtu is out of range. - */ - -static int sppp_change_mtu(struct net_device *dev, int new_mtu) -{ - if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP)) - return -EINVAL; - dev->mtu=new_mtu; - return 0; -} - -/** - * sppp_do_ioctl - Ioctl handler for ppp/hdlc - * @dev: Device subject to ioctl - * @ifr: Interface request block from the user - * @cmd: Command that is being issued - * - * This function handles the ioctls that may be issued by the user - * to control the settings of a PPP/HDLC link. It does both busy - * and security checks. This function is intended to be wrapped by - * callers who wish to add additional ioctl calls of their own. - */ - -int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - - if(dev->flags&IFF_UP) - return -EBUSY; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch(cmd) - { - case SPPPIOCCISCO: - sp->pp_flags|=PP_CISCO; - dev->type = ARPHRD_HDLC; - break; - case SPPPIOCPPP: - sp->pp_flags&=~PP_CISCO; - dev->type = ARPHRD_PPP; - break; - case SPPPIOCDEBUG: - sp->pp_flags&=~PP_DEBUG; - if(ifr->ifr_flags) - sp->pp_flags|=PP_DEBUG; - break; - case SPPPIOCGFLAGS: - if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags))) - return -EFAULT; - break; - case SPPPIOCSFLAGS: - if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags))) - return -EFAULT; - break; - default: - return -EINVAL; - } - return 0; -} - -EXPORT_SYMBOL(sppp_do_ioctl); - -/** - * sppp_attach - attach synchronous PPP/HDLC to a device - * @pd: PPP device to initialise - * - * This initialises the PPP/HDLC support on an interface. At the - * time of calling the dev element must point to the network device - * that this interface is attached to. The interface should not yet - * be registered. - */ - -void sppp_attach(struct ppp_device *pd) -{ - struct net_device *dev = pd->dev; - struct sppp *sp = &pd->sppp; - unsigned long flags; - - /* Make sure embedding is safe for sppp_of */ - BUG_ON(sppp_of(dev) != sp); - - spin_lock_irqsave(&spppq_lock, flags); - /* Initialize keepalive handler. */ - if (! spppq) - { - init_timer(&sppp_keepalive_timer); - sppp_keepalive_timer.expires=jiffies+10*HZ; - sppp_keepalive_timer.function=sppp_keepalive; - add_timer(&sppp_keepalive_timer); - } - /* Insert new entry into the keepalive list. */ - sp->pp_next = spppq; - spppq = sp; - spin_unlock_irqrestore(&spppq_lock, flags); - - sp->pp_loopcnt = 0; - sp->pp_alivecnt = 0; - sp->pp_seq = 0; - sp->pp_rseq = 0; - sp->pp_flags = PP_KEEPALIVE|PP_CISCO|debug;/*PP_DEBUG;*/ - sp->lcp.magic = 0; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sp->pp_if = dev; - spin_lock_init(&sp->lock); - - /* - * Device specific setup. All but interrupt handler and - * hard_start_xmit. - */ - - dev->header_ops = &sppp_header_ops; - - dev->tx_queue_len = 10; - dev->type = ARPHRD_HDLC; - dev->addr_len = 0; - dev->hard_header_len = sizeof(struct ppp_header); - dev->mtu = PPP_MTU; - /* - * These 4 are callers but MUST also call sppp_ functions - */ - dev->do_ioctl = sppp_do_ioctl; -#if 0 - dev->get_stats = NULL; /* Let the driver override these */ - dev->open = sppp_open; - dev->stop = sppp_close; -#endif - dev->change_mtu = sppp_change_mtu; - dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP; -} - -EXPORT_SYMBOL(sppp_attach); - -/** - * sppp_detach - release PPP resources from a device - * @dev: Network device to release - * - * Stop and free up any PPP/HDLC resources used by this - * interface. This must be called before the device is - * freed. - */ - -void sppp_detach (struct net_device *dev) -{ - struct sppp **q, *p, *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - spin_lock_irqsave(&spppq_lock, flags); - /* Remove the entry from the keepalive list. */ - for (q = &spppq; (p = *q); q = &p->pp_next) - if (p == sp) { - *q = p->pp_next; - break; - } - - /* Stop keepalive handler. */ - if (! spppq) - del_timer(&sppp_keepalive_timer); - sppp_clear_timeout (sp); - spin_unlock_irqrestore(&spppq_lock, flags); -} - -EXPORT_SYMBOL(sppp_detach); - -/* - * Analyze the LCP Configure-Request options list - * for the presence of unknown options. - * If the request contains unknown options, build and - * send Configure-reject packet, containing only unknown options. - */ -static int -sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, - int len, u32 *magic) -{ - u8 *buf, *r, *p; - int rlen; - - len -= 4; - buf = r = kmalloc (len, GFP_ATOMIC); - if (! buf) - return (0); - - p = (void*) (h+1); - for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { - switch (*p) { - case LCP_OPT_MAGIC: - /* Magic number -- extract. */ - if (len >= 6 && p[1] == 6) { - *magic = (u32)p[2] << 24 | - (u32)p[3] << 16 | p[4] << 8 | p[5]; - continue; - } - break; - case LCP_OPT_ASYNC_MAP: - /* Async control character map -- check to be zero. */ - if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && - ! p[4] && ! p[5]) - continue; - break; - case LCP_OPT_MRU: - /* Maximum receive unit -- always OK. */ - continue; - default: - /* Others not supported. */ - break; - } - /* Add the option to rejected list. */ - memcpy(r, p, p[1]); - r += p[1]; - rlen += p[1]; - } - if (rlen) - sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf); - kfree(buf); - return (rlen == 0); -} - -static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb) -{ - struct lcp_header *h; - struct net_device *dev = sp->pp_if; - int len = skb->len; - - if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n", - dev->name, len); - return; - } - h = (struct lcp_header *)skb->data; - skb_pull(skb,sizeof(struct lcp_header)); - if (sp->pp_flags & PP_DEBUG) { - printk (KERN_WARNING "%s: ipcp input: %d bytes <%s id=%xh len=%xh", - dev->name, len, - sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); - if (len > 4) - sppp_print_bytes ((u8*) (h+1), len-4); - printk (">\n"); - } - if (len > ntohs (h->len)) - len = ntohs (h->len); - switch (h->type) { - default: - /* Unknown packet type -- send Code-Reject packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); - break; - case IPCP_CONF_REQ: - if (len < 4) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid ipcp configure request packet length: %d bytes\n", - dev->name, len); - return; - } - if (len > 4) { - sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, - len-4, h+1); - - switch (sp->ipcp.state) { - case IPCP_STATE_OPENED: - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - /* fall through... */ - case IPCP_STATE_ACK_SENT: - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - } - } else { - /* Send Configure-Ack packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, - 0, NULL); - /* Change the state. */ - if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) - sp->ipcp.state = IPCP_STATE_OPENED; - else - sp->ipcp.state = IPCP_STATE_ACK_SENT; - } - break; - case IPCP_CONF_ACK: - if (h->ident != sp->ipcp.confid) - break; - sppp_clear_timeout (sp); - switch (sp->ipcp.state) { - case IPCP_STATE_CLOSED: - sp->ipcp.state = IPCP_STATE_ACK_RCVD; - sppp_set_timeout (sp, 5); - break; - case IPCP_STATE_ACK_SENT: - sp->ipcp.state = IPCP_STATE_OPENED; - break; - } - break; - case IPCP_CONF_NAK: - case IPCP_CONF_REJ: - if (h->ident != sp->ipcp.confid) - break; - sppp_clear_timeout (sp); - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - if (sp->ipcp.state != IPCP_STATE_ACK_SENT) - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - break; - case IPCP_TERM_REQ: - /* Send Terminate-Ack packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, NULL); - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - break; - case IPCP_TERM_ACK: - /* Ignore for now. */ - case IPCP_CODE_REJ: - /* Ignore for now. */ - break; - } -} - -static void sppp_lcp_open (struct sppp *sp) -{ - char opt[6]; - - if (! sp->lcp.magic) - sp->lcp.magic = jiffies; - opt[0] = LCP_OPT_MAGIC; - opt[1] = sizeof (opt); - opt[2] = sp->lcp.magic >> 24; - opt[3] = sp->lcp.magic >> 16; - opt[4] = sp->lcp.magic >> 8; - opt[5] = sp->lcp.magic; - sp->lcp.confid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, - sizeof (opt), &opt); - sppp_set_timeout (sp, 2); -} - -static void sppp_ipcp_open (struct sppp *sp) -{ - sp->ipcp.confid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, NULL); - sppp_set_timeout (sp, 2); -} - -/* - * Process PPP control protocol timeouts. - */ - -static void sppp_cp_timeout (unsigned long arg) -{ - struct sppp *sp = (struct sppp*) arg; - unsigned long flags; - - spin_lock_irqsave(&sp->lock, flags); - - sp->pp_flags &= ~PP_TIMO; - if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) { - spin_unlock_irqrestore(&sp->lock, flags); - return; - } - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - /* No ACK for Configure-Request, retry. */ - sppp_lcp_open (sp); - break; - case LCP_STATE_ACK_RCVD: - /* ACK got, but no Configure-Request for peer, retry. */ - sppp_lcp_open (sp); - sp->lcp.state = LCP_STATE_CLOSED; - break; - case LCP_STATE_ACK_SENT: - /* ACK sent but no ACK for Configure-Request, retry. */ - sppp_lcp_open (sp); - break; - case LCP_STATE_OPENED: - /* LCP is already OK, try IPCP. */ - switch (sp->ipcp.state) { - case IPCP_STATE_CLOSED: - /* No ACK for Configure-Request, retry. */ - sppp_ipcp_open (sp); - break; - case IPCP_STATE_ACK_RCVD: - /* ACK got, but no Configure-Request for peer, retry. */ - sppp_ipcp_open (sp); - sp->ipcp.state = IPCP_STATE_CLOSED; - break; - case IPCP_STATE_ACK_SENT: - /* ACK sent but no ACK for Configure-Request, retry. */ - sppp_ipcp_open (sp); - break; - case IPCP_STATE_OPENED: - /* IPCP is OK. */ - break; - } - break; - } - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); -} - -static char *sppp_lcp_type_name (u8 type) -{ - static char buf [8]; - switch (type) { - case LCP_CONF_REQ: return ("conf-req"); - case LCP_CONF_ACK: return ("conf-ack"); - case LCP_CONF_NAK: return ("conf-nack"); - case LCP_CONF_REJ: return ("conf-rej"); - case LCP_TERM_REQ: return ("term-req"); - case LCP_TERM_ACK: return ("term-ack"); - case LCP_CODE_REJ: return ("code-rej"); - case LCP_PROTO_REJ: return ("proto-rej"); - case LCP_ECHO_REQ: return ("echo-req"); - case LCP_ECHO_REPLY: return ("echo-reply"); - case LCP_DISC_REQ: return ("discard-req"); - } - sprintf (buf, "%xh", type); - return (buf); -} - -static char *sppp_ipcp_type_name (u8 type) -{ - static char buf [8]; - switch (type) { - case IPCP_CONF_REQ: return ("conf-req"); - case IPCP_CONF_ACK: return ("conf-ack"); - case IPCP_CONF_NAK: return ("conf-nack"); - case IPCP_CONF_REJ: return ("conf-rej"); - case IPCP_TERM_REQ: return ("term-req"); - case IPCP_TERM_ACK: return ("term-ack"); - case IPCP_CODE_REJ: return ("code-rej"); - } - sprintf (buf, "%xh", type); - return (buf); -} - -static void sppp_print_bytes (u_char *p, u16 len) -{ - printk (" %x", *p++); - while (--len > 0) - printk ("-%x", *p++); -} - -/** - * sppp_rcv - receive and process a WAN PPP frame - * @skb: The buffer to process - * @dev: The device it arrived on - * @p: Unused - * @orig_dev: Unused - * - * Protocol glue. This drives the deferred processing mode the poorer - * cards use. This can be called directly by cards that do not have - * timing constraints but is normally called from the network layer - * after interrupt servicing to process frames queued via netif_rx. - */ - -static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) -{ - if (dev->nd_net != &init_net) { - kfree_skb(skb); - return 0; - } - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - sppp_input(dev,skb); - return 0; -} - -static struct packet_type sppp_packet_type = { - .type = __constant_htons(ETH_P_WAN_PPP), - .func = sppp_rcv, -}; - -static char banner[] __initdata = - KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" - KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " - "Jan \"Yenya\" Kasprzak.\n"; - -static int __init sync_ppp_init(void) -{ - if(debug) - debug=PP_DEBUG; - printk(banner); - skb_queue_head_init(&tx_queue); - dev_add_pack(&sppp_packet_type); - return 0; -} - - -static void __exit sync_ppp_cleanup(void) -{ - dev_remove_pack(&sppp_packet_type); -} - -module_init(sync_ppp_init); -module_exit(sync_ppp_cleanup); -module_param(debug, int, 0); -MODULE_LICENSE("GPL"); - diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index d4aab8a28b6..f76aa908158 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -13,6 +13,8 @@ * - wanXL100 will require minor driver modifications, no access to hw */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -22,6 +24,7 @@ #include <linux/string.h> #include <linux/errno.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/netdevice.h> #include <linux/hdlc.h> @@ -101,9 +104,8 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr, { dma_addr_t addr = pci_map_single(pdev, ptr, size, direction); if (addr + size > 0x100000000LL) - printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory" - " at 0x%LX!\n", pci_name(pdev), - (unsigned long long)addr); + pr_crit("%s: pci_map_single() returned memory at 0x%llx!\n", + pci_name(pdev), (unsigned long long)addr); return addr; } @@ -146,8 +148,8 @@ static inline void wanxl_cable_intr(port_t *port) } dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE"; } - printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n", - port->dev->name, pm, dte, cable, dsr, dcd); + netdev_info(port->dev, "%s%s module, %s cable%s%s\n", + pm, dte, cable, dsr, dcd); if (value & STATUS_CABLE_DCD) netif_carrier_on(port->dev); @@ -161,7 +163,6 @@ static inline void wanxl_cable_intr(port_t *port) static inline void wanxl_tx_intr(port_t *port) { struct net_device *dev = port->dev; - struct net_device_stats *stats = hdlc_stats(dev); while (1) { desc_t *desc = &get_status(port)->tx_descs[port->tx_in]; struct sk_buff *skb = port->tx_skbs[port->tx_in]; @@ -173,13 +174,13 @@ static inline void wanxl_tx_intr(port_t *port) return; case PACKET_UNDERRUN: - stats->tx_errors++; - stats->tx_fifo_errors++; + dev->stats.tx_errors++; + dev->stats.tx_fifo_errors++; break; default: - stats->tx_packets++; - stats->tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; } desc->stat = PACKET_EMPTY; /* Free descriptor */ pci_unmap_single(port->card->pdev, desc->address, skb->len, @@ -198,17 +199,16 @@ static inline void wanxl_rx_intr(card_t *card) while (desc = &card->status->rx_descs[card->rx_in], desc->stat != PACKET_EMPTY) { if ((desc->stat & PACKET_PORT_MASK) > card->n_ports) - printk(KERN_CRIT "wanXL %s: received packet for" - " nonexistent port\n", pci_name(card->pdev)); + pr_crit("%s: received packet for nonexistent port\n", + pci_name(card->pdev)); else { struct sk_buff *skb = card->rx_skbs[card->rx_in]; port_t *port = &card->ports[desc->stat & PACKET_PORT_MASK]; struct net_device *dev = port->dev; - struct net_device_stats *stats = hdlc_stats(dev); if (!skb) - stats->rx_dropped++; + dev->stats.rx_dropped++; else { pci_unmap_single(card->pdev, desc->address, BUFFER_LENGTH, @@ -220,9 +220,8 @@ static inline void wanxl_rx_intr(card_t *card) skb->len); debug_frame(skb); #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; - dev->last_rx = jiffies; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); skb = NULL; @@ -271,7 +270,7 @@ static irqreturn_t wanxl_intr(int irq, void* dev_id) -static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev) { port_t *port = dev_to_port(dev); desc_t *desc; @@ -285,8 +284,8 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name); #endif netif_stop_queue(dev); - spin_unlock_irq(&port->lock); - return 1; /* request packet to be queued */ + spin_unlock(&port->lock); + return NETDEV_TX_BUSY; /* request packet to be queued */ } #ifdef DEBUG_PKT @@ -301,7 +300,6 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) desc->stat = PACKET_FULL; writel(1 << (DOORBELL_TO_CARD_TX_0 + port->node), port->card->plx + PLX_DOORBELL_TO_CARD); - dev->trans_start = jiffies; port->tx_out = (port->tx_out + 1) % TX_BUFFERS; @@ -313,7 +311,7 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) } spin_unlock(&port->lock); - return 0; + return NETDEV_TX_OK; } @@ -357,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } + memset(&line, 0, sizeof(line)); line.clock_type = get_status(port)->clocking; line.clock_rate = 0; line.loopback = 0; @@ -400,7 +399,7 @@ static int wanxl_open(struct net_device *dev) int i; if (get_status(port)->open) { - printk(KERN_ERR "%s: port already open\n", dev->name); + netdev_err(dev, "port already open\n"); return -EIO; } if ((i = hdlc_open(dev)) != 0) @@ -413,14 +412,14 @@ static int wanxl_open(struct net_device *dev) writel(1 << (DOORBELL_TO_CARD_OPEN_0 + port->node), dbr); timeout = jiffies + HZ; - do + do { if (get_status(port)->open) { netif_start_queue(dev); return 0; } - while (time_after(timeout, jiffies)); + } while (time_after(timeout, jiffies)); - printk(KERN_ERR "%s: unable to open port\n", dev->name); + netdev_err(dev, "unable to open port\n"); /* ask the card to close the port, should it be still alive */ writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr); return -EFAULT; @@ -440,13 +439,13 @@ static int wanxl_close(struct net_device *dev) port->card->plx + PLX_DOORBELL_TO_CARD); timeout = jiffies + HZ; - do + do { if (!get_status(port)->open) break; - while (time_after(timeout, jiffies)); + } while (time_after(timeout, jiffies)); if (get_status(port)->open) - printk(KERN_ERR "%s: unable to close port\n", dev->name); + netdev_err(dev, "unable to close port\n"); netif_stop_queue(dev); @@ -468,13 +467,13 @@ static int wanxl_close(struct net_device *dev) static struct net_device_stats *wanxl_get_stats(struct net_device *dev) { - struct net_device_stats *stats = hdlc_stats(dev); port_t *port = dev_to_port(dev); - stats->rx_over_errors = get_status(port)->rx_overruns; - stats->rx_frame_errors = get_status(port)->rx_frame_errors; - stats->rx_errors = stats->rx_over_errors + stats->rx_frame_errors; - return stats; + dev->stats.rx_over_errors = get_status(port)->rx_overruns; + dev->stats.rx_frame_errors = get_status(port)->rx_frame_errors; + dev->stats.rx_errors = dev->stats.rx_over_errors + + dev->stats.rx_frame_errors; + return &dev->stats; } @@ -543,15 +542,23 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); kfree(card); } #include "wanxlfw.inc" -static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static const struct net_device_ops wanxl_ops = { + .ndo_open = wanxl_open, + .ndo_stop = wanxl_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = wanxl_ioctl, + .ndo_get_stats = wanxl_get_stats, +}; + +static int wanxl_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { card_t *card; u32 ramsize, stat; @@ -562,11 +569,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, int i, ports, alloc_size; #ifndef MODULE - static int printed_version; - if (!printed_version) { - printed_version++; - printk(KERN_INFO "%s\n", version); - } + pr_info_once("%s\n", version); #endif i = pci_enable_device(pdev); @@ -580,9 +583,9 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, We set both dma_mask and consistent_dma_mask to 28 bits and pray pci_alloc_consistent() will use this info. It should work on most platforms */ - if (pci_set_consistent_dma_mask(pdev, DMA_28BIT_MASK) || - pci_set_dma_mask(pdev, DMA_28BIT_MASK)) { - printk(KERN_ERR "wanXL: No usable DMA configuration\n"); + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(28)) || + pci_set_dma_mask(pdev, DMA_BIT_MASK(28))) { + pr_err("No usable DMA configuration\n"); return -EIO; } @@ -601,8 +604,6 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, alloc_size = sizeof(card_t) + ports * sizeof(port_t); card = kzalloc(alloc_size, GFP_KERNEL); if (card == NULL) { - printk(KERN_ERR "wanXL %s: unable to allocate memory\n", - pci_name(pdev)); pci_release_regions(pdev); pci_disable_device(pdev); return -ENOBUFS; @@ -627,9 +628,9 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, /* FIXME when PCI/DMA subsystems are fixed. We set both dma_mask and consistent_dma_mask back to 32 bits to indicate the card can do 32-bit DMA addressing */ - if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) || - pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_ERR "wanXL: No usable DMA configuration\n"); + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) || + pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + pr_err("No usable DMA configuration\n"); wanxl_pci_remove_one(pdev); return -EIO; } @@ -639,7 +640,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, card->plx = ioremap_nocache(plx_phy, 0x70); if (!card->plx) { - printk(KERN_ERR "wanxl: ioremap() failed\n"); + pr_err("ioremap() failed\n"); wanxl_pci_remove_one(pdev); return -EFAULT; } @@ -651,8 +652,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, timeout = jiffies + 20 * HZ; while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) { if (time_before(timeout, jiffies)) { - printk(KERN_WARNING "wanXL %s: timeout waiting for" - " PUTS to complete\n", pci_name(pdev)); + pr_warn("%s: timeout waiting for PUTS to complete\n", + pci_name(pdev)); wanxl_pci_remove_one(pdev); return -ENODEV; } @@ -663,8 +664,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, break; default: - printk(KERN_WARNING "wanXL %s: PUTS test 0x%X" - " failed\n", pci_name(pdev), stat & 0x30); + pr_warn("%s: PUTS test 0x%X failed\n", + pci_name(pdev), stat & 0x30); wanxl_pci_remove_one(pdev); return -ENODEV; } @@ -682,17 +683,16 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, /* sanity check the board's reported memory size */ if (ramsize < BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) { - printk(KERN_WARNING "wanXL %s: no enough on-board RAM" - " (%u bytes detected, %u bytes required)\n", - pci_name(pdev), ramsize, BUFFERS_ADDR + - (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports); + pr_warn("%s: no enough on-board RAM (%u bytes detected, %u bytes required)\n", + pci_name(pdev), ramsize, + BUFFERS_ADDR + + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports); wanxl_pci_remove_one(pdev); return -ENODEV; } if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) { - printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap" - " Mode\n", pci_name(pdev)); + pr_warn("%s: unable to Set Byte Swap Mode\n", pci_name(pdev)); wanxl_pci_remove_one(pdev); return -ENODEV; } @@ -709,7 +709,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware)); if (!mem) { - printk(KERN_ERR "wanxl: ioremap() failed\n"); + pr_err("ioremap() failed\n"); wanxl_pci_remove_one(pdev); return -EFAULT; } @@ -728,8 +728,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, writel(0, card->plx + PLX_MAILBOX_5); if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) { - printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n", - pci_name(pdev)); + pr_warn("%s: unable to Abort and Jump\n", pci_name(pdev)); wanxl_pci_remove_one(pdev); return -ENODEV; } @@ -743,8 +742,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, }while (time_after(timeout, jiffies)); if (!stat) { - printk(KERN_WARNING "wanXL %s: timeout while initializing card " - "firmware\n", pci_name(pdev)); + pr_warn("%s: timeout while initializing card firmware\n", + pci_name(pdev)); wanxl_pci_remove_one(pdev); return -ENODEV; } @@ -753,13 +752,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, ramsize = stat; #endif - printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n", - pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq); + pr_info("%s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n", + pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq); /* Allocate IRQ */ if (request_irq(pdev->irq, wanxl_intr, IRQF_SHARED, "wanXL", card)) { - printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n", - pci_name(pdev), pdev->irq); + pr_warn("%s: could not allocate IRQ%i\n", + pci_name(pdev), pdev->irq); wanxl_pci_remove_one(pdev); return -EBUSY; } @@ -770,8 +769,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, port_t *port = &card->ports[i]; struct net_device *dev = alloc_hdlcdev(port); if (!dev) { - printk(KERN_ERR "wanXL %s: unable to allocate" - " memory\n", pci_name(pdev)); + pr_err("%s: unable to allocate memory\n", + pci_name(pdev)); wanxl_pci_remove_one(pdev); return -ENOMEM; } @@ -780,18 +779,15 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, hdlc = dev_to_hdlc(dev); spin_lock_init(&port->lock); dev->tx_queue_len = 50; - dev->do_ioctl = wanxl_ioctl; - dev->open = wanxl_open; - dev->stop = wanxl_close; + dev->netdev_ops = &wanxl_ops; hdlc->attach = wanxl_attach; hdlc->xmit = wanxl_xmit; - dev->get_stats = wanxl_get_stats; port->card = card; port->node = i; get_status(port)->clocking = CLOCK_EXT; if (register_hdlc_device(dev)) { - printk(KERN_ERR "wanXL %s: unable to register hdlc" - " device\n", pci_name(pdev)); + pr_err("%s: unable to register hdlc device\n", + pci_name(pdev)); free_netdev(dev); wanxl_pci_remove_one(pdev); return -ENOBUFS; @@ -799,11 +795,11 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, card->n_ports++; } - printk(KERN_INFO "wanXL %s: port", pci_name(pdev)); + pr_info("%s: port", pci_name(pdev)); for (i = 0; i < ports; i++) - printk("%s #%i: %s", i ? "," : "", i, - card->ports[i].dev->name); - printk("\n"); + pr_cont("%s #%i: %s", + i ? "," : "", i, card->ports[i].dev->name); + pr_cont("\n"); for (i = 0; i < ports; i++) wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/ @@ -811,7 +807,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, return 0; } -static struct pci_device_id wanxl_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(wanxl_pci_tbl) = { { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID, @@ -833,7 +829,7 @@ static struct pci_driver wanxl_pci_driver = { static int __init wanxl_init_module(void) { #ifdef MODULE - printk(KERN_INFO "%s\n", version); + pr_info("%s\n", version); #endif return pci_register_driver(&wanxl_pci_driver); } diff --git a/drivers/net/wan/wanxlfw.S b/drivers/net/wan/wanxlfw.S index 73aae2bf2f1..21565d59ec7 100644 --- a/drivers/net/wan/wanxlfw.S +++ b/drivers/net/wan/wanxlfw.S @@ -35,6 +35,7 @@ */ #include <linux/hdlc.h> +#include <linux/hdlc/ioctl.h> #include "wanxl.h" /* memory addresses and offsets */ diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 0f8aca8a4d4..fa9fdfa128c 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -14,10 +14,11 @@ * 2000-10-29 Henner Eisen lapb_data_indication() return status. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> -#include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/bitops.h> #include <linux/string.h> #include <linux/mm.h> @@ -29,12 +30,13 @@ #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <linux/if_arp.h> -#include <linux/x25.h> #include <linux/lapb.h> #include <linux/init.h> -#include "x25_asy.h" - +#include <linux/rtnetlink.h> +#include <linux/compat.h> +#include <linux/slab.h> #include <net/x25device.h> +#include "x25_asy.h" static struct net_device **x25_asy_devs; static int x25_asy_maxdev = SL_NRUNIT; @@ -63,7 +65,7 @@ static struct x25_asy *x25_asy_alloc(void) if (dev == NULL) break; - sl = dev->priv; + sl = netdev_priv(dev); /* Not in use ? */ if (!test_and_set_bit(SLF_INUSE, &sl->flags)) return sl; @@ -85,7 +87,7 @@ static struct x25_asy *x25_asy_alloc(void) return NULL; /* Initialize channel control data */ - sl = dev->priv; + sl = netdev_priv(dev); dev->base_addr = i; /* register device so that it can be ifconfig'ed */ @@ -95,7 +97,7 @@ static struct x25_asy *x25_asy_alloc(void) x25_asy_devs[i] = dev; return sl; } else { - printk("x25_asy_alloc() - register_netdev() failure.\n"); + pr_warn("%s(): register_netdev() failure\n", __func__); free_netdev(dev); } } @@ -112,24 +114,24 @@ static void x25_asy_free(struct x25_asy *sl) kfree(sl->xbuff); sl->xbuff = NULL; - if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) { - printk("%s: x25_asy_free for already free unit.\n", sl->dev->name); - } + if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) + netdev_err(sl->dev, "x25_asy_free for already free unit\n"); } static int x25_asy_change_mtu(struct net_device *dev, int newmtu) { - struct x25_asy *sl = dev->priv; + struct x25_asy *sl = netdev_priv(dev); unsigned char *xbuff, *rbuff; - int len = 2* newmtu; + int len; + if (newmtu > 65534) + return -EINVAL; + + len = 2 * newmtu; xbuff = kmalloc(len + 4, GFP_ATOMIC); rbuff = kmalloc(len + 4, GFP_ATOMIC); - if (xbuff == NULL || rbuff == NULL) - { - printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n", - dev->name); + if (xbuff == NULL || rbuff == NULL) { kfree(xbuff); kfree(rbuff); return -ENOMEM; @@ -142,7 +144,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) memcpy(sl->xbuff, sl->xhead, sl->xleft); } else { sl->xleft = 0; - sl->stats.tx_dropped++; + dev->stats.tx_dropped++; } } sl->xhead = sl->xbuff; @@ -153,7 +155,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) memcpy(sl->rbuff, rbuff, sl->rcount); } else { sl->rcount = 0; - sl->stats.rx_over_errors++; + dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -188,33 +190,30 @@ static inline void x25_asy_unlock(struct x25_asy *sl) static void x25_asy_bump(struct x25_asy *sl) { + struct net_device *dev = sl->dev; struct sk_buff *skb; int count; int err; count = sl->rcount; - sl->stats.rx_bytes+=count; - + dev->stats.rx_bytes += count; + skb = dev_alloc_skb(count+1); - if (skb == NULL) - { - printk("%s: memory squeeze, dropping packet.\n", sl->dev->name); - sl->stats.rx_dropped++; + if (skb == NULL) { + netdev_warn(sl->dev, "memory squeeze, dropping packet\n"); + dev->stats.rx_dropped++; return; } - skb_push(skb,1); /* LAPB internal control */ - memcpy(skb_put(skb,count), sl->rbuff, count); + skb_push(skb, 1); /* LAPB internal control */ + memcpy(skb_put(skb, count), sl->rbuff, count); skb->protocol = x25_type_trans(skb, sl->dev); - if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK) - { + err = lapb_data_received(skb->dev, skb); + if (err != LAPB_OK) { kfree_skb(skb); - printk(KERN_DEBUG "x25_asy: data received err - %d\n",err); - } - else - { + printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); + } else { netif_rx(skb); - sl->dev->last_rx = jiffies; - sl->stats.rx_packets++; + dev->stats.rx_packets++; } } @@ -224,17 +223,18 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) unsigned char *p; int actual, count, mtu = sl->dev->mtu; - if (len > mtu) - { /* Sigh, shouldn't occur BUT ... */ + if (len > mtu) { + /* Sigh, shouldn't occur BUT ... */ len = mtu; - printk ("%s: truncating oversized transmit packet!\n", sl->dev->name); - sl->stats.tx_dropped++; + printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", + sl->dev->name); + sl->dev->stats.tx_dropped++; x25_asy_unlock(sl); return; } p = icp; - count = x25_asy_esc(p, (unsigned char *) sl->xbuff, len); + count = x25_asy_esc(p, sl->xbuff, len); /* Order of next two lines is *very* important. * When we are sending a little amount of data, @@ -244,8 +244,8 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) * if we did not request it before write operation. * 14 Oct 1994 Dmitry Gorodchanin. */ - sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); + set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); + actual = sl->tty->ops->write(sl->tty, sl->xbuff, count); sl->xleft = count - actual; sl->xhead = sl->xbuff + actual; /* VSV */ @@ -259,41 +259,40 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) static void x25_asy_write_wakeup(struct tty_struct *tty) { int actual; - struct x25_asy *sl = (struct x25_asy *) tty->disc_data; + struct x25_asy *sl = tty->disc_data; /* First make sure we're connected. */ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev)) return; - if (sl->xleft <= 0) - { + if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ - sl->stats.tx_packets++; - tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + sl->dev->stats.tx_packets++; + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); x25_asy_unlock(sl); return; } - actual = tty->driver->write(tty, sl->xhead, sl->xleft); + actual = tty->ops->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; } static void x25_asy_timeout(struct net_device *dev) { - struct x25_asy *sl = (struct x25_asy*)(dev->priv); + struct x25_asy *sl = netdev_priv(dev); spin_lock(&sl->lock); if (netif_queue_stopped(dev)) { /* May be we must check transmitter timeout here ? * 14 Oct 1994 Dmitry Gorodchanin. */ - printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, - (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ? - "bad line quality" : "driver error"); + netdev_warn(dev, "transmit timed out, %s?\n", + (tty_chars_in_buffer(sl->tty) || sl->xleft) ? + "bad line quality" : "driver error"); sl->xleft = 0; - sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); x25_asy_unlock(sl); } spin_unlock(&sl->lock); @@ -301,33 +300,38 @@ static void x25_asy_timeout(struct net_device *dev) /* Encapsulate an IP datagram and kick it into a TTY queue. */ -static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t x25_asy_xmit(struct sk_buff *skb, + struct net_device *dev) { - struct x25_asy *sl = (struct x25_asy*)(dev->priv); + struct x25_asy *sl = netdev_priv(dev); int err; if (!netif_running(sl->dev)) { - printk("%s: xmit call when iface is down\n", dev->name); + netdev_err(dev, "xmit call when iface is down\n"); kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } - - switch(skb->data[0]) - { - case 0x00:break; - case 0x01: /* Connection request .. do nothing */ - if((err=lapb_connect_request(dev))!=LAPB_OK) - printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err); - kfree_skb(skb); - return 0; - case 0x02: /* Disconnect request .. do nothing - hang up ?? */ - if((err=lapb_disconnect_request(dev))!=LAPB_OK) - printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err); - default: - kfree_skb(skb); - return 0; + + switch (skb->data[0]) { + case X25_IFACE_DATA: + break; + case X25_IFACE_CONNECT: /* Connection request .. do nothing */ + err = lapb_connect_request(dev); + if (err != LAPB_OK) + netdev_err(dev, "lapb_connect_request error: %d\n", + err); + kfree_skb(skb); + return NETDEV_TX_OK; + case X25_IFACE_DISCONNECT: /* do nothing - hang up ?? */ + err = lapb_disconnect_request(dev); + if (err != LAPB_OK) + netdev_err(dev, "lapb_disconnect_request error: %d\n", + err); + default: + kfree_skb(skb); + return NETDEV_TX_OK; } - skb_pull(skb,1); /* Remove control byte */ + skb_pull(skb, 1); /* Remove control byte */ /* * If we are busy already- too bad. We ought to be able * to queue things at this point, to allow for a little @@ -338,14 +342,14 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) * So, no queues ! * 14 Oct 1994 Dmitry Gorodchanin. */ - - if((err=lapb_data_request(dev,skb))!=LAPB_OK) - { - printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err); + + err = lapb_data_request(dev, skb); + if (err != LAPB_OK) { + netdev_err(dev, "lapb_data_request error: %d\n", err); kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } - return 0; + return NETDEV_TX_OK; } @@ -357,10 +361,9 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) * Called when I frame data arrives. We did the work above - throw it * at the net layer. */ - + static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) { - skb->dev->last_rx = jiffies; return netif_rx(skb); } @@ -369,24 +372,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) * busy cases too well. Its tricky to see how to do this nicely - * perhaps lapb should allow us to bounce this ? */ - + static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) { - struct x25_asy *sl=dev->priv; - + struct x25_asy *sl = netdev_priv(dev); + spin_lock(&sl->lock); - if (netif_queue_stopped(sl->dev) || sl->tty == NULL) - { + if (netif_queue_stopped(sl->dev) || sl->tty == NULL) { spin_unlock(&sl->lock); - printk(KERN_ERR "x25_asy: tbusy drop\n"); + netdev_err(dev, "tbusy drop\n"); kfree_skb(skb); return; } /* We were not busy, so we are now... :-) */ - if (skb != NULL) - { + if (skb != NULL) { x25_asy_lock(sl); - sl->stats.tx_bytes+=skb->len; + dev->stats.tx_bytes += skb->len; x25_asy_encaps(sl, skb->data, skb->len); dev_kfree_skb(skb); } @@ -396,60 +397,59 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) /* * LAPB connection establish/down information. */ - + static void x25_asy_connected(struct net_device *dev, int reason) { - struct x25_asy *sl = dev->priv; + struct x25_asy *sl = netdev_priv(dev); struct sk_buff *skb; unsigned char *ptr; - if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "lapbeth: out of memory\n"); + skb = dev_alloc_skb(1); + if (skb == NULL) { + netdev_err(dev, "out of memory\n"); return; } ptr = skb_put(skb, 1); - *ptr = 0x01; + *ptr = X25_IFACE_CONNECT; skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); - sl->dev->last_rx = jiffies; } static void x25_asy_disconnected(struct net_device *dev, int reason) { - struct x25_asy *sl = dev->priv; + struct x25_asy *sl = netdev_priv(dev); struct sk_buff *skb; unsigned char *ptr; - if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "x25_asy: out of memory\n"); + skb = dev_alloc_skb(1); + if (skb == NULL) { + netdev_err(dev, "out of memory\n"); return; } ptr = skb_put(skb, 1); - *ptr = 0x02; + *ptr = X25_IFACE_DISCONNECT; skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); - sl->dev->last_rx = jiffies; } -static struct lapb_register_struct x25_asy_callbacks = { +static const struct lapb_register_struct x25_asy_callbacks = { .connect_confirmation = x25_asy_connected, .connect_indication = x25_asy_connected, .disconnect_confirmation = x25_asy_disconnected, .disconnect_indication = x25_asy_disconnected, .data_indication = x25_asy_data_indication, .data_transmit = x25_asy_data_transmit, - }; /* Open the low-level part of the X.25 channel. Easy! */ static int x25_asy_open(struct net_device *dev) { - struct x25_asy *sl = (struct x25_asy*)(dev->priv); + struct x25_asy *sl = netdev_priv(dev); unsigned long len; int err; @@ -466,13 +466,11 @@ static int x25_asy_open(struct net_device *dev) len = dev->mtu * 2; sl->rbuff = kmalloc(len + 4, GFP_KERNEL); - if (sl->rbuff == NULL) { + if (sl->rbuff == NULL) goto norbuff; - } sl->xbuff = kmalloc(len + 4, GFP_KERNEL); - if (sl->xbuff == NULL) { + if (sl->xbuff == NULL) goto noxbuff; - } sl->buffsize = len; sl->rcount = 0; @@ -480,11 +478,12 @@ static int x25_asy_open(struct net_device *dev) sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ netif_start_queue(dev); - + /* * Now attach LAPB */ - if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK) + err = lapb_register(dev, &x25_asy_callbacks); + if (err == LAPB_OK) return 0; /* Cleanup */ @@ -499,18 +498,15 @@ norbuff: /* Close the low-level part of the X.25 channel. Easy! */ static int x25_asy_close(struct net_device *dev) { - struct x25_asy *sl = (struct x25_asy*)(dev->priv); - int err; + struct x25_asy *sl = netdev_priv(dev); spin_lock(&sl->lock); - if (sl->tty) - sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + if (sl->tty) + clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); netif_stop_queue(dev); sl->rcount = 0; sl->xleft = 0; - if((err=lapb_unregister(dev))!=LAPB_OK) - printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err); spin_unlock(&sl->lock); return 0; } @@ -521,10 +517,11 @@ static int x25_asy_close(struct net_device *dev) * a block of X.25 data has been received, which can now be decapsulated * and sent on to some IP layer for further processing. */ - -static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) + +static void x25_asy_receive_buf(struct tty_struct *tty, + const unsigned char *cp, char *fp, int count) { - struct x25_asy *sl = (struct x25_asy *) tty->disc_data; + struct x25_asy *sl = tty->disc_data; if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev)) return; @@ -533,9 +530,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, /* Read the characters out of the buffer */ while (count--) { if (fp && *fp++) { - if (!test_and_set_bit(SLF_ERROR, &sl->flags)) { - sl->stats.rx_errors++; - } + if (!test_and_set_bit(SLF_ERROR, &sl->flags)) + sl->dev->stats.rx_errors++; cp++; continue; } @@ -553,36 +549,36 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, static int x25_asy_open_tty(struct tty_struct *tty) { - struct x25_asy *sl = (struct x25_asy *) tty->disc_data; + struct x25_asy *sl = tty->disc_data; int err; + if (tty->ops->write == NULL) + return -EOPNOTSUPP; + /* First make sure we're not already connected. */ - if (sl && sl->magic == X25_ASY_MAGIC) { + if (sl && sl->magic == X25_ASY_MAGIC) return -EEXIST; - } /* OK. Find a free X.25 channel to use. */ - if ((sl = x25_asy_alloc()) == NULL) { + sl = x25_asy_alloc(); + if (sl == NULL) return -ENFILE; - } sl->tty = tty; tty->disc_data = sl; tty->receive_room = 65536; - if (tty->driver->flush_buffer) { - tty->driver->flush_buffer(tty); - } + tty_driver_flush_buffer(tty); tty_ldisc_flush(tty); /* Restore default settings */ sl->dev->type = ARPHRD_X25; - + /* Perform the low-level X.25 async init */ - if ((err = x25_asy_open(sl->dev))) + err = x25_asy_open(sl->dev); + if (err) return err; - /* Done. We have linked the TTY line to a channel. */ - return sl->dev->base_addr; + return 0; } @@ -594,36 +590,33 @@ static int x25_asy_open_tty(struct tty_struct *tty) */ static void x25_asy_close_tty(struct tty_struct *tty) { - struct x25_asy *sl = (struct x25_asy *) tty->disc_data; + struct x25_asy *sl = tty->disc_data; + int err; /* First make sure we're connected. */ if (!sl || sl->magic != X25_ASY_MAGIC) return; + rtnl_lock(); if (sl->dev->flags & IFF_UP) - { - (void) dev_close(sl->dev); - } + dev_close(sl->dev); + rtnl_unlock(); + + err = lapb_unregister(sl->dev); + if (err != LAPB_OK) + pr_err("x25_asy_close: lapb_unregister error: %d\n", + err); tty->disc_data = NULL; sl->tty = NULL; x25_asy_free(sl); } - -static struct net_device_stats *x25_asy_get_stats(struct net_device *dev) -{ - struct x25_asy *sl = (struct x25_asy*)(dev->priv); - - return &sl->stats; -} - - /************************************************************************ * STANDARD X.25 ENCAPSULATION * ************************************************************************/ -int x25_asy_esc(unsigned char *s, unsigned char *d, int len) +static int x25_asy_esc(unsigned char *s, unsigned char *d, int len) { unsigned char *ptr = d; unsigned char c; @@ -641,59 +634,51 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len) * character sequence, according to the X.25 protocol. */ - while (len-- > 0) - { - switch(c = *s++) - { - case X25_END: - *ptr++ = X25_ESC; - *ptr++ = X25_ESCAPE(X25_END); - break; - case X25_ESC: - *ptr++ = X25_ESC; - *ptr++ = X25_ESCAPE(X25_ESC); - break; - default: - *ptr++ = c; - break; + while (len-- > 0) { + switch (c = *s++) { + case X25_END: + *ptr++ = X25_ESC; + *ptr++ = X25_ESCAPE(X25_END); + break; + case X25_ESC: + *ptr++ = X25_ESC; + *ptr++ = X25_ESCAPE(X25_ESC); + break; + default: + *ptr++ = c; + break; } } *ptr++ = X25_END; - return (ptr - d); + return ptr - d; } static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) { - switch(s) - { - case X25_END: - if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2)) - { - x25_asy_bump(sl); - } - clear_bit(SLF_ESCAPE, &sl->flags); - sl->rcount = 0; - return; - - case X25_ESC: - set_bit(SLF_ESCAPE, &sl->flags); - return; - - case X25_ESCAPE(X25_ESC): - case X25_ESCAPE(X25_END): - if (test_and_clear_bit(SLF_ESCAPE, &sl->flags)) - s = X25_UNESCAPE(s); - break; - } - if (!test_bit(SLF_ERROR, &sl->flags)) - { - if (sl->rcount < sl->buffsize) - { + switch (s) { + case X25_END: + if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && + sl->rcount > 2) + x25_asy_bump(sl); + clear_bit(SLF_ESCAPE, &sl->flags); + sl->rcount = 0; + return; + case X25_ESC: + set_bit(SLF_ESCAPE, &sl->flags); + return; + case X25_ESCAPE(X25_ESC): + case X25_ESCAPE(X25_END): + if (test_and_clear_bit(SLF_ESCAPE, &sl->flags)) + s = X25_UNESCAPE(s); + break; + } + if (!test_bit(SLF_ERROR, &sl->flags)) { + if (sl->rcount < sl->buffsize) { sl->rbuff[sl->rcount++] = s; return; } - sl->stats.rx_over_errors++; + sl->dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -703,13 +688,13 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - struct x25_asy *sl = (struct x25_asy *) tty->disc_data; + struct x25_asy *sl = tty->disc_data; /* First make sure we're connected. */ if (!sl || sl->magic != X25_ASY_MAGIC) return -EINVAL; - switch(cmd) { + switch (cmd) { case SIOCGIFNAME: if (copy_to_user((void __user *)arg, sl->dev->name, strlen(sl->dev->name) + 1)) @@ -722,18 +707,41 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, } } +#ifdef CONFIG_COMPAT +static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case SIOCGIFNAME: + case SIOCSIFHWADDR: + return x25_asy_ioctl(tty, file, cmd, + (unsigned long)compat_ptr(arg)); + } + + return -ENOIOCTLCMD; +} +#endif + static int x25_asy_open_dev(struct net_device *dev) { - struct x25_asy *sl = (struct x25_asy*)(dev->priv); - if(sl->tty==NULL) + struct x25_asy *sl = netdev_priv(dev); + if (sl->tty == NULL) return -ENODEV; return 0; } +static const struct net_device_ops x25_asy_netdev_ops = { + .ndo_open = x25_asy_open_dev, + .ndo_stop = x25_asy_close, + .ndo_start_xmit = x25_asy_xmit, + .ndo_tx_timeout = x25_asy_timeout, + .ndo_change_mtu = x25_asy_change_mtu, +}; + /* Initialise the X.25 driver. Called by the device init code */ static void x25_asy_setup(struct net_device *dev) { - struct x25_asy *sl = dev->priv; + struct x25_asy *sl = netdev_priv(dev); sl->magic = X25_ASY_MAGIC; sl->dev = dev; @@ -741,17 +749,12 @@ static void x25_asy_setup(struct net_device *dev) set_bit(SLF_INUSE, &sl->flags); /* - * Finish setting up the DEVICE info. + * Finish setting up the DEVICE info. */ - + dev->mtu = SL_MTU; - dev->hard_start_xmit = x25_asy_xmit; - dev->tx_timeout = x25_asy_timeout; + dev->netdev_ops = &x25_asy_netdev_ops; dev->watchdog_timeo = HZ*20; - dev->open = x25_asy_open_dev; - dev->stop = x25_asy_close; - dev->get_stats = x25_asy_get_stats; - dev->change_mtu = x25_asy_change_mtu; dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_X25; @@ -761,13 +764,16 @@ static void x25_asy_setup(struct net_device *dev) dev->flags = IFF_NOARP; } -static struct tty_ldisc x25_ldisc = { +static struct tty_ldisc_ops x25_ldisc = { .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, .name = "X.25", .open = x25_asy_open_tty, .close = x25_asy_close_tty, .ioctl = x25_asy_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = x25_asy_compat_ioctl, +#endif .receive_buf = x25_asy_receive_buf, .write_wakeup = x25_asy_write_wakeup, }; @@ -777,15 +783,13 @@ static int __init init_x25_asy(void) if (x25_asy_maxdev < 4) x25_asy_maxdev = 4; /* Sanity */ - printk(KERN_INFO "X.25 async: version 0.00 ALPHA " - "(dynamic channels, max=%d).\n", x25_asy_maxdev ); + pr_info("X.25 async: version 0.00 ALPHA (dynamic channels, max=%d)\n", + x25_asy_maxdev); - x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL); - if (!x25_asy_devs) { - printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] " - "array! Uaargh! (-> No X.25 available)\n"); + x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *), + GFP_KERNEL); + if (!x25_asy_devs) return -ENOMEM; - } return tty_register_ldisc(N_X25, &x25_ldisc); } @@ -799,10 +803,10 @@ static void __exit exit_x25_asy(void) for (i = 0; i < x25_asy_maxdev; i++) { dev = x25_asy_devs[i]; if (dev) { - struct x25_asy *sl = dev->priv; + struct x25_asy *sl = netdev_priv(dev); spin_lock_bh(&sl->lock); - if (sl->tty) + if (sl->tty) tty_hangup(sl->tty); spin_unlock_bh(&sl->lock); diff --git a/drivers/net/wan/x25_asy.h b/drivers/net/wan/x25_asy.h index 41770200ceb..f57ee67836a 100644 --- a/drivers/net/wan/x25_asy.h +++ b/drivers/net/wan/x25_asy.h @@ -28,10 +28,6 @@ struct x25_asy { unsigned char *xbuff; /* transmitter buffer */ unsigned char *xhead; /* pointer to next byte to XMIT */ int xleft; /* bytes left in XMIT queue */ - - /* X.25 interface statistics. */ - struct net_device_stats stats; - int buffsize; /* Max buffers sizes */ unsigned long flags; /* Flag values/ mode etc */ @@ -45,6 +41,6 @@ struct x25_asy { #define X25_ASY_MAGIC 0x5303 -extern int x25_asy_init(struct net_device *dev); +int x25_asy_init(struct net_device *dev); #endif /* _LINUX_X25_ASY.H */ diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index 98ef400908b..feacc3b994b 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -18,7 +18,8 @@ * DMA now uses get_free_page as kmalloc buffers may span a 64K * boundary. * - * Modified for SMP safety and SMP locking by Alan Cox <alan@redhat.com> + * Modified for SMP safety and SMP locking by Alan Cox + * <alan@lxorguk.ukuu.org.uk> * * Performance * @@ -35,6 +36,8 @@ * Synchronous mode without DMA is unlikely to pass about 2400 baud. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -43,15 +46,16 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/delay.h> +#include <linux/hdlc.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/gfp.h> #include <asm/dma.h> #include <asm/io.h> #define RT_LOCK #define RT_UNLOCK #include <linux/spinlock.h> -#include <net/syncppp.h> #include "z85230.h" @@ -363,7 +367,7 @@ static void z8530_rx(struct z8530_channel *c) c->count=0; if(stat&Rx_OVR) { - printk(KERN_WARNING "%s: overrun\n", c->dev->name); + pr_warn("%s: overrun\n", c->dev->name); c->rx_overrun++; } if(stat&CRC_ERR) @@ -440,51 +444,46 @@ static void z8530_tx(struct z8530_channel *c) * A status event occurred in PIO synchronous mode. There are several * reasons the chip will bother us here. A transmit underrun means we * failed to feed the chip fast enough and just broke a packet. A DCD - * change is a line up or down. We communicate that back to the protocol - * layer for synchronous PPP to renegotiate. + * change is a line up or down. */ static void z8530_status(struct z8530_channel *chan) { u8 status, altered; - status=read_zsreg(chan, R0); - altered=chan->status^status; - - chan->status=status; - - if(status&TxEOM) - { + status = read_zsreg(chan, R0); + altered = chan->status ^ status; + + chan->status = status; + + if (status & TxEOM) { /* printk("%s: Tx underrun.\n", chan->dev->name); */ - chan->stats.tx_fifo_errors++; + chan->netdevice->stats.tx_fifo_errors++; write_zsctrl(chan, ERR_RES); z8530_tx_done(chan); } - - if(altered&chan->dcdcheck) + + if (altered & chan->dcdcheck) { - if(status&chan->dcdcheck) - { - printk(KERN_INFO "%s: DCD raised\n", chan->dev->name); - write_zsreg(chan, R3, chan->regs[3]|RxENABLE); - if(chan->netdevice && - ((chan->netdevice->type == ARPHRD_HDLC) || - (chan->netdevice->type == ARPHRD_PPP))) - sppp_reopen(chan->netdevice); - } - else - { - printk(KERN_INFO "%s: DCD lost\n", chan->dev->name); - write_zsreg(chan, R3, chan->regs[3]&~RxENABLE); + if (status & chan->dcdcheck) { + pr_info("%s: DCD raised\n", chan->dev->name); + write_zsreg(chan, R3, chan->regs[3] | RxENABLE); + if (chan->netdevice) + netif_carrier_on(chan->netdevice); + } else { + pr_info("%s: DCD lost\n", chan->dev->name); + write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE); z8530_flush_fifo(chan); + if (chan->netdevice) + netif_carrier_off(chan->netdevice); } - - } + + } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); } -struct z8530_irqhandler z8530_sync= +struct z8530_irqhandler z8530_sync = { z8530_rx, z8530_tx, @@ -541,12 +540,12 @@ static void z8530_dma_tx(struct z8530_channel *chan) { if(!chan->dma_tx) { - printk(KERN_WARNING "Hey who turned the DMA off?\n"); + pr_warn("Hey who turned the DMA off?\n"); z8530_tx(chan); return; } - /* This shouldnt occur in DMA mode */ - printk(KERN_ERR "DMA tx - bogus event!\n"); + /* This shouldn't occur in DMA mode */ + pr_err("DMA tx - bogus event!\n"); z8530_tx(chan); } @@ -556,8 +555,7 @@ static void z8530_dma_tx(struct z8530_channel *chan) * * A status event occurred on the Z8530. We receive these for two reasons * when in DMA mode. Firstly if we finished a packet transfer we get one - * and kick the next packet out. Secondly we may see a DCD change and - * have to poke the protocol layer. + * and kick the next packet out. Secondly we may see a DCD change. * */ @@ -586,47 +584,38 @@ static void z8530_dma_status(struct z8530_channel *chan) } } - if(altered&chan->dcdcheck) + if (altered & chan->dcdcheck) { - if(status&chan->dcdcheck) - { - printk(KERN_INFO "%s: DCD raised\n", chan->dev->name); - write_zsreg(chan, R3, chan->regs[3]|RxENABLE); - if(chan->netdevice && - ((chan->netdevice->type == ARPHRD_HDLC) || - (chan->netdevice->type == ARPHRD_PPP))) - sppp_reopen(chan->netdevice); - } - else - { - printk(KERN_INFO "%s:DCD lost\n", chan->dev->name); - write_zsreg(chan, R3, chan->regs[3]&~RxENABLE); + if (status & chan->dcdcheck) { + pr_info("%s: DCD raised\n", chan->dev->name); + write_zsreg(chan, R3, chan->regs[3] | RxENABLE); + if (chan->netdevice) + netif_carrier_on(chan->netdevice); + } else { + pr_info("%s: DCD lost\n", chan->dev->name); + write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE); z8530_flush_fifo(chan); + if (chan->netdevice) + netif_carrier_off(chan->netdevice); } - } + } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); } -struct z8530_irqhandler z8530_dma_sync= -{ +static struct z8530_irqhandler z8530_dma_sync = { z8530_dma_rx, z8530_dma_tx, z8530_dma_status }; -EXPORT_SYMBOL(z8530_dma_sync); - -struct z8530_irqhandler z8530_txdma_sync= -{ +static struct z8530_irqhandler z8530_txdma_sync = { z8530_rx, z8530_dma_tx, z8530_dma_status }; -EXPORT_SYMBOL(z8530_txdma_sync); - /** * z8530_rx_clear - Handle RX events from a stopped chip * @c: Z8530 channel to shut up @@ -703,7 +692,6 @@ EXPORT_SYMBOL(z8530_nop); * z8530_interrupt - Handle an interrupt from a Z8530 * @irq: Interrupt number * @dev_id: The Z8530 device that is interrupting. - * @regs: unused * * A Z85[2]30 device has stuck its hand in the air for attention. * We scan both the channels on the chip for events and then call @@ -719,14 +707,14 @@ EXPORT_SYMBOL(z8530_nop); irqreturn_t z8530_interrupt(int irq, void *dev_id) { struct z8530_dev *dev=dev_id; - u8 intr; + u8 uninitialized_var(intr); static volatile int locker=0; int work=0; struct z8530_irqhandler *irqs; if(locker) { - printk(KERN_ERR "IRQ re-enter\n"); + pr_err("IRQ re-enter\n"); return IRQ_NONE; } locker=1; @@ -772,7 +760,8 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id) } spin_unlock(&dev->lock); if(work==5000) - printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr); + pr_err("%s: interrupt jammed - abort(0x%X)!\n", + dev->name, intr); /* Ok all done */ locker=0; return IRQ_HANDLED; @@ -780,7 +769,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id) EXPORT_SYMBOL(z8530_interrupt); -static char reg_init[16]= +static const u8 reg_init[16]= { 0,0,0,0, 0,0,0,0, @@ -1220,7 +1209,7 @@ EXPORT_SYMBOL(z8530_sync_txdma_close); * it exists... */ -static char *z8530_type_name[]={ +static const char *z8530_type_name[]={ "Z8530", "Z85C30", "Z85230" @@ -1233,13 +1222,13 @@ static char *z8530_type_name[]={ * @io: the port value in question * * Describe a Z8530 in a standard format. We must pass the I/O as - * the port offset isnt predictable. The main reason for this function + * the port offset isn't predictable. The main reason for this function * is to try and get a common format of report. */ void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io) { - printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n", + pr_info("%s: %s found at %s 0x%lX, IRQ %d\n", dev->name, z8530_type_name[dev->type], mapping, @@ -1459,10 +1448,10 @@ static void z8530_tx_begin(struct z8530_channel *c) /* * Check if we crapped out. */ - if(get_dma_residue(c->txdma)) + if (get_dma_residue(c->txdma)) { - c->stats.tx_dropped++; - c->stats.tx_fifo_errors++; + c->netdevice->stats.tx_dropped++; + c->netdevice->stats.tx_fifo_errors++; } release_dma_lock(flags); } @@ -1534,21 +1523,21 @@ static void z8530_tx_begin(struct z8530_channel *c) * packet. This code is fairly timing sensitive. * * Called with the register lock held. - */ - + */ + static void z8530_tx_done(struct z8530_channel *c) { struct sk_buff *skb; /* Actually this can happen.*/ - if(c->tx_skb==NULL) + if (c->tx_skb == NULL) return; - skb=c->tx_skb; - c->tx_skb=NULL; + skb = c->tx_skb; + c->tx_skb = NULL; z8530_tx_begin(c); - c->stats.tx_packets++; - c->stats.tx_bytes+=skb->len; + c->netdevice->stats.tx_packets++; + c->netdevice->stats.tx_bytes += skb->len; dev_kfree_skb_irq(skb); } @@ -1558,7 +1547,7 @@ static void z8530_tx_done(struct z8530_channel *c) * @skb: The buffer * * We point the receive handler at this function when idle. Instead - * of syncppp processing the frames we get to throw them away. + * of processing the frames we get to throw them away. */ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb) @@ -1602,7 +1591,7 @@ static void z8530_rx_done(struct z8530_channel *c) unsigned long flags; /* - * Complete this DMA. Neccessary to find the length + * Complete this DMA. Necessary to find the length */ flags=claim_dma_lock(); @@ -1635,10 +1624,10 @@ static void z8530_rx_done(struct z8530_channel *c) else /* Can't occur as we dont reenable the DMA irq until after the flip is done */ - printk(KERN_WARNING "%s: DMA flip overrun!\n", c->netdevice->name); - + netdev_warn(c->netdevice, "DMA flip overrun!\n"); + release_dma_lock(flags); - + /* * Shove the old buffer into an sk_buff. We can't DMA * directly into one on a PC - it might be above the 16Mb @@ -1646,27 +1635,22 @@ static void z8530_rx_done(struct z8530_channel *c) * can avoid the copy. Optimisation 2 - make the memcpy * a copychecksum. */ - - skb=dev_alloc_skb(ct); - if(skb==NULL) - { - c->stats.rx_dropped++; - printk(KERN_WARNING "%s: Memory squeeze.\n", c->netdevice->name); - } - else - { + + skb = dev_alloc_skb(ct); + if (skb == NULL) { + c->netdevice->stats.rx_dropped++; + netdev_warn(c->netdevice, "Memory squeeze\n"); + } else { skb_put(skb, ct); skb_copy_to_linear_data(skb, rxb, ct); - c->stats.rx_packets++; - c->stats.rx_bytes+=ct; + c->netdevice->stats.rx_packets++; + c->netdevice->stats.rx_bytes += ct; } - c->dma_ready=1; - } - else - { - RT_LOCK; - skb=c->skb; - + c->dma_ready = 1; + } else { + RT_LOCK; + skb = c->skb; + /* * The game we play for non DMA is similar. We want to * get the controller set up for the next packet as fast @@ -1674,52 +1658,42 @@ static void z8530_rx_done(struct z8530_channel *c) * fifo length for this. Thus we want to flip to the new * buffer and then mess around copying and allocating * things. For the current case it doesn't matter but - * if you build a system where the sync irq isnt blocked + * if you build a system where the sync irq isn't blocked * by the kernel IRQ disable then you need only block the * sync IRQ for the RT_LOCK area. - * + * */ ct=c->count; - + c->skb = c->skb2; c->count = 0; c->max = c->mtu; - if(c->skb) - { + if (c->skb) { c->dptr = c->skb->data; c->max = c->mtu; - } - else - { - c->count= 0; + } else { + c->count = 0; c->max = 0; } RT_UNLOCK; c->skb2 = dev_alloc_skb(c->mtu); - if(c->skb2==NULL) - printk(KERN_WARNING "%s: memory squeeze.\n", - c->netdevice->name); + if (c->skb2 == NULL) + netdev_warn(c->netdevice, "memory squeeze\n"); else - { - skb_put(c->skb2,c->mtu); - } - c->stats.rx_packets++; - c->stats.rx_bytes+=ct; - + skb_put(c->skb2, c->mtu); + c->netdevice->stats.rx_packets++; + c->netdevice->stats.rx_bytes += ct; } /* * If we received a frame we must now process it. */ - if(skb) - { + if (skb) { skb_trim(skb, ct); - c->rx_function(c,skb); - } - else - { - c->stats.rx_dropped++; - printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name); + c->rx_function(c, skb); + } else { + c->netdevice->stats.rx_dropped++; + netdev_err(c->netdevice, "Lost a frame\n"); } } @@ -1730,7 +1704,7 @@ static void z8530_rx_done(struct z8530_channel *c) * Returns true if the buffer cross a DMA boundary on a PC. The poor * thing can only DMA within a 64K block not across the edges of it. */ - + static inline int spans_boundary(struct sk_buff *skb) { unsigned long a=(unsigned long)skb->data; @@ -1754,15 +1728,14 @@ static inline int spans_boundary(struct sk_buff *skb) * point. */ -int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb) +netdev_tx_t z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb) { unsigned long flags; netif_stop_queue(c->netdevice); if(c->tx_next_skb) - { - return 1; - } + return NETDEV_TX_BUSY; + /* PC SPECIFIC - DMA limits */ @@ -1794,33 +1767,16 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb) z8530_tx_begin(c); spin_unlock_irqrestore(c->lock, flags); - return 0; + return NETDEV_TX_OK; } EXPORT_SYMBOL(z8530_queue_xmit); -/** - * z8530_get_stats - Get network statistics - * @c: The channel to use - * - * Get the statistics block. We keep the statistics in software as - * the chip doesn't do it for us. - * - * Locking is ignored here - we could lock for a copy but its - * not likely to be that big an issue - */ - -struct net_device_stats *z8530_get_stats(struct z8530_channel *c) -{ - return &c->stats; -} - -EXPORT_SYMBOL(z8530_get_stats); - /* * Module support */ -static char banner[] __initdata = KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; +static const char banner[] __initconst = + KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; static int __init z85230_init_driver(void) { diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h index 158aea7b8ea..2416a9d60bd 100644 --- a/drivers/net/wan/z85230.h +++ b/drivers/net/wan/z85230.h @@ -2,7 +2,7 @@ * Description of Z8530 Z85C30 and Z85230 communications chips * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 Alan Cox <alan@redhat.com> + * Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk> */ #ifndef _Z8530_H @@ -325,7 +325,6 @@ struct z8530_channel void *private; /* For our owner */ struct net_device *netdevice; /* Network layer device */ - struct net_device_stats stats; /* Network layer statistics */ /* * Async features @@ -366,13 +365,13 @@ struct z8530_channel unsigned char tx_active; /* character is being xmitted */ unsigned char tx_stopped; /* output is suspended */ - spinlock_t *lock; /* Devicr lock */ -}; + spinlock_t *lock; /* Device lock */ +}; /* * Each Z853x0 device. - */ - + */ + struct z8530_dev { char *name; /* Device instance name */ @@ -396,20 +395,19 @@ 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 *); -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 *); -extern int z8530_sync_open(struct net_device *, struct z8530_channel *); -extern int z8530_sync_close(struct net_device *, struct z8530_channel *); -extern int z8530_sync_dma_open(struct net_device *, struct z8530_channel *); -extern int z8530_sync_dma_close(struct net_device *, struct z8530_channel *); -extern int z8530_sync_txdma_open(struct net_device *, struct z8530_channel *); -extern int z8530_sync_txdma_close(struct net_device *, struct z8530_channel *); -extern int z8530_channel_load(struct z8530_channel *, u8 *); -extern int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb); -extern struct net_device_stats *z8530_get_stats(struct z8530_channel *c); -extern void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb); +irqreturn_t z8530_interrupt(int, void *); +void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io); +int z8530_init(struct z8530_dev *); +int z8530_shutdown(struct z8530_dev *); +int z8530_sync_open(struct net_device *, struct z8530_channel *); +int z8530_sync_close(struct net_device *, struct z8530_channel *); +int z8530_sync_dma_open(struct net_device *, struct z8530_channel *); +int z8530_sync_dma_close(struct net_device *, struct z8530_channel *); +int z8530_sync_txdma_open(struct net_device *, struct z8530_channel *); +int z8530_sync_txdma_close(struct net_device *, struct z8530_channel *); +int z8530_channel_load(struct z8530_channel *, u8 *); +netdev_tx_t z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb); +void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb); /* |
