diff options
Diffstat (limited to 'drivers/net/hamradio/6pack.c')
| -rw-r--r-- | drivers/net/hamradio/6pack.c | 198 |
1 files changed, 101 insertions, 97 deletions
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 90999867a32..66e2b19ef70 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -3,7 +3,7 @@ * devices like TTY. It interfaces between a raw TTY and the * kernel's AX.25 protocol layers. * - * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de> + * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de> * Ralf Baechle DL5RB <ralf@linux-mips.org> * * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by @@ -12,9 +12,7 @@ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> */ -#include <linux/config.h> #include <linux/module.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <linux/bitops.h> #include <linux/string.h> @@ -25,6 +23,7 @@ #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/timer.h> +#include <linux/slab.h> #include <net/ax25.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> @@ -34,8 +33,9 @@ #include <linux/init.h> #include <linux/ip.h> #include <linux/tcp.h> -#include <asm/semaphore.h> -#include <asm/atomic.h> +#include <linux/semaphore.h> +#include <linux/compat.h> +#include <linux/atomic.h> #define SIXPACK_VERSION "Revision: 0.3.0" @@ -100,9 +100,6 @@ struct sixpack { unsigned int rx_count; unsigned int rx_count_cooked; - /* 6pack interface statistics. */ - struct net_device_stats stats; - int mtu; /* Our mtu (to spot changes!) */ int buffsize; /* Max buffers sizes */ @@ -149,13 +146,13 @@ static void sp_xmit_on_air(unsigned long channel) if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); + actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); sp->status2 = 0; } else mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100); @@ -221,13 +218,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) */ if (sp->duplex == 1) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, sp->xbuff, count); + actual = sp->tty->ops->write(sp->tty, sp->xbuff, count); sp->xleft = count - actual; sp->xhead = sp->xbuff + actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); } else { sp->xleft = count; sp->xhead = sp->xbuff; @@ -238,7 +235,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) return; out_drop: - sp->stats.tx_dropped++; + sp->dev->stats.tx_dropped++; netif_start_queue(sp->dev); if (net_ratelimit()) printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg); @@ -246,20 +243,20 @@ out_drop: /* Encapsulate an IP datagram and kick it into a TTY queue. */ -static int sp_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev) { struct sixpack *sp = netdev_priv(dev); spin_lock_bh(&sp->lock); /* We were not busy, so we are now... :-) */ netif_stop_queue(dev); - sp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; sp_encaps(sp, skb->data, skb->len); spin_unlock_bh(&sp->lock); dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } static int sp_open_dev(struct net_device *dev) @@ -289,28 +286,25 @@ static int sp_close(struct net_device *dev) /* Return the frame type ID */ static int sp_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) + unsigned short type, const void *daddr, + const void *saddr, unsigned len) { #ifdef CONFIG_INET - if (type != htons(ETH_P_AX25)) + if (type != ETH_P_AX25) return ax25_hard_header(skb, dev, type, daddr, saddr, len); #endif return 0; } -static struct net_device_stats *sp_get_stats(struct net_device *dev) -{ - struct sixpack *sp = netdev_priv(dev); - return &sp->stats; -} - static int sp_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); + netif_addr_lock(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_addr_unlock(dev); + netif_tx_unlock_bh(dev); return 0; } @@ -324,34 +318,34 @@ static int sp_rebuild_header(struct sk_buff *skb) #endif } +static const struct header_ops sp_header_ops = { + .create = sp_header, + .rebuild = sp_rebuild_header, +}; + +static const struct net_device_ops sp_netdev_ops = { + .ndo_open = sp_open_dev, + .ndo_stop = sp_close, + .ndo_start_xmit = sp_xmit, + .ndo_set_mac_address = sp_set_mac_address, +}; + static void sp_setup(struct net_device *dev) { - static char ax25_bcast[AX25_ADDR_LEN] = - {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; - static char ax25_test[AX25_ADDR_LEN] = - {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; - /* Finish setting up the DEVICE info. */ - dev->mtu = SIXP_MTU; - dev->hard_start_xmit = sp_xmit; - dev->open = sp_open_dev; + dev->netdev_ops = &sp_netdev_ops; dev->destructor = free_netdev; - dev->stop = sp_close; - dev->hard_header = sp_header; - dev->get_stats = sp_get_stats; - dev->set_mac_address = sp_set_mac_address; + dev->mtu = SIXP_MTU; dev->hard_header_len = AX25_MAX_HEADER_LEN; + dev->header_ops = &sp_header_ops; + dev->addr_len = AX25_ADDR_LEN; dev->type = ARPHRD_AX25; dev->tx_queue_len = 10; - dev->rebuild_header = sp_rebuild_header; - dev->tx_timeout = NULL; /* Only activated in AX.25 mode */ - memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); - memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); - - SET_MODULE_OWNER(dev); + memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); + memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); dev->flags = 0; } @@ -371,7 +365,7 @@ static void sp_bump(struct sixpack *sp, char cmd) count = sp->rcount + 1; - sp->stats.rx_bytes += count; + sp->dev->stats.rx_bytes += count; if ((skb = dev_alloc_skb(count)) == NULL) goto out_mem; @@ -382,13 +376,12 @@ static void sp_bump(struct sixpack *sp, char cmd) memcpy(ptr, sp->cooked_buf + 1, count); skb->protocol = ax25_type_trans(skb, sp->dev); netif_rx(skb); - sp->dev->last_rx = jiffies; - sp->stats.rx_packets++; + sp->dev->stats.rx_packets++; return; out_mem: - sp->stats.rx_dropped++; + sp->dev->stats.rx_dropped++; } @@ -437,7 +430,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty) if (sp->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ - sp->stats.tx_packets++; + sp->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sp->tx_enable = 0; netif_wake_queue(sp->dev); @@ -445,7 +438,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty) } if (sp->tx_enable) { - actual = tty->driver->write(tty, sp->xhead, sp->xleft); + actual = tty->ops->write(tty, sp->xhead, sp->xleft); sp->xleft -= actual; sp->xhead += actual; } @@ -456,11 +449,6 @@ out: /* ----------------------------------------------------------------------- */ -static int sixpack_receive_room(struct tty_struct *tty) -{ - return 65536; /* We can handle an infinite amount of data. :-) */ -} - /* * Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when @@ -490,16 +478,14 @@ static void sixpack_receive_buf(struct tty_struct *tty, count--; if (fp && *fp++) { if (!test_and_set_bit(SIXPF_ERROR, &sp->flags)) - sp->stats.rx_errors++; + sp->dev->stats.rx_errors++; continue; } } sixpack_decode(sp, buf, count1); sp_put(sp); - if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) - && tty->driver->unthrottle) - tty->driver->unthrottle(tty); + tty_unthrottle(tty); } /* @@ -560,8 +546,8 @@ static void resync_tnc(unsigned long channel) /* resync the TNC */ sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); - sp->tty->driver->write(sp->tty, &resync_cmd, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &resync_cmd, 1); /* Start resync timer again -- the TNC might be still absent */ @@ -579,7 +565,7 @@ static inline int tnc_init(struct sixpack *sp) tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP); - sp->tty->driver->write(sp->tty, &inbyte, 1); + sp->tty->ops->write(sp->tty, &inbyte, 1); del_timer(&sp->resync_t); sp->resync_t.data = (unsigned long) sp; @@ -607,6 +593,8 @@ static int sixpack_open(struct tty_struct *tty) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (tty->ops->write == NULL) + return -EOPNOTSUPP; dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup); if (!dev) { @@ -619,7 +607,7 @@ static int sixpack_open(struct tty_struct *tty) spin_lock_init(&sp->lock); atomic_set(&sp->refcnt, 1); - init_MUTEX_LOCKED(&sp->dead_sem); + sema_init(&sp->dead_sem, 0); /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */ @@ -671,9 +659,11 @@ static int sixpack_open(struct tty_struct *tty) /* Done. We have linked the TTY line to a channel. */ tty->disc_data = sp; + tty->receive_room = 65536; /* Now we're ready to register. */ - if (register_netdev(dev)) + err = register_netdev(dev); + if (err) goto out_free; tnc_init(sp); @@ -702,11 +692,11 @@ static void sixpack_close(struct tty_struct *tty) { struct sixpack *sp; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); sp = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); - if (sp == 0) + write_unlock_bh(&disc_data_lock); + if (!sp) return; /* @@ -731,11 +721,12 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct sixpack *sp = sp_get(tty); - struct net_device *dev = sp->dev; + struct net_device *dev; unsigned int tmp, err; if (!sp) return -ENXIO; + dev = sp->dev; switch(cmd) { case SIOCGIFNAME: @@ -767,26 +758,20 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, if (copy_from_user(&addr, (void __user *) arg, AX25_ADDR_LEN)) { - err = -EFAULT; - break; - } - - spin_lock_irq(&dev->xmit_lock); - memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + err = -EFAULT; + break; + } - err = 0; - break; - } + netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); + netif_tx_unlock_bh(dev); - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, (struct file *) file, cmd, arg); - break; + err = 0; + break; + } default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); } sp_put(sp); @@ -794,23 +779,42 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, return err; } -static struct tty_ldisc sp_ldisc = { +#ifdef CONFIG_COMPAT +static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case SIOCGIFNAME: + case SIOCGIFENCAP: + case SIOCSIFENCAP: + case SIOCSIFHWADDR: + return sixpack_ioctl(tty, file, cmd, + (unsigned long)compat_ptr(arg)); + } + + return -ENOIOCTLCMD; +} +#endif + +static struct tty_ldisc_ops sp_ldisc = { .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, .name = "6pack", .open = sixpack_open, .close = sixpack_close, .ioctl = sixpack_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sixpack_compat_ioctl, +#endif .receive_buf = sixpack_receive_buf, - .receive_room = sixpack_receive_room, .write_wakeup = sixpack_write_wakeup, }; /* Initialize 6pack control device -- register 6pack line discipline */ -static char msg_banner[] __initdata = KERN_INFO \ +static const char msg_banner[] __initconst = KERN_INFO \ "AX.25: 6pack driver, " SIXPACK_VERSION "\n"; -static char msg_regfail[] __initdata = KERN_ERR \ +static const char msg_regfail[] __initconst = KERN_ERR \ "6pack: can't register line discipline (err = %d)\n"; static int __init sixpack_init_driver(void) @@ -826,7 +830,7 @@ static int __init sixpack_init_driver(void) return status; } -static const char msg_unregfail[] __exitdata = KERN_ERR \ +static const char msg_unregfail[] = KERN_ERR \ "6pack: can't unregister line discipline (err = %d)\n"; static void __exit sixpack_exit_driver(void) @@ -920,15 +924,15 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd) printk(KERN_DEBUG "6pack: protocol violation\n"); else sp->status = 0; - cmd &= !SIXP_RX_DCD_MASK; + cmd &= ~SIXP_RX_DCD_MASK; } sp->status = cmd & SIXP_PRIO_DATA_MASK; } else { /* output watchdog char if idle */ if ((sp->status2 != 0) && (sp->duplex == 1)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); + actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; @@ -938,7 +942,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd) } /* needed to trigger the TNC watchdog */ - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); /* if the state byte has been received, the TNC is present, so the resync timer can be reset. */ @@ -968,12 +972,12 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd) if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) { sp->led_state = 0x68; - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); } } else { sp->led_state = 0x60; /* fill trailing bytes with zeroes */ - sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->ops->write(sp->tty, &sp->led_state, 1); rest = sp->rx_count; if (rest != 0) for (i = rest; i <= 3; i++) |
